diff options
author | Jens Axboe <jaxboe@fusionio.com> | 2010-10-19 11:13:04 +0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-10-19 11:13:04 +0400 |
commit | fa251f89903d73989e2f63e13d0eaed1e07ce0da (patch) | |
tree | 3f7fe779941e3b6d67754dd7c44a32f48ea47c74 /drivers | |
parent | dd3932eddf428571762596e17b65f5dc92ca361b (diff) | |
parent | cd07202cc8262e1669edff0d97715f3dd9260917 (diff) | |
download | linux-fa251f89903d73989e2f63e13d0eaed1e07ce0da.tar.xz |
Merge branch 'v2.6.36-rc8' into for-2.6.37/barrier
Conflicts:
block/blk-core.c
drivers/block/loop.c
mm/swapfile.c
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'drivers')
570 files changed, 8117 insertions, 8206 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index ae473445ad6d..a2aea53a75ed 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -50,7 +50,7 @@ obj-$(CONFIG_SPI) += spi/ obj-y += net/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ -obj-$(CONFIG_FIREWIRE) += firewire/ +obj-y += firewire/ obj-y += ieee1394/ obj-$(CONFIG_UIO) += uio/ obj-y += cdrom/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b811f2173f6f..88681aca88c5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -105,7 +105,7 @@ config ACPI_EC_DEBUGFS Be aware that using this interface can confuse your Embedded Controller in a way that a normal reboot is not enough. You then - have to power of your system, and remove the laptop battery for + have to power off your system, and remove the laptop battery for some seconds. An Embedded Controller typically is available on laptops and reads sensor values like battery state and temperature. diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index b76848c80be3..6b115f6c4313 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -382,31 +382,32 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) device_remove_file(&device->dev, &dev_attr_rrtime); } -/* Query firmware how many CPUs should be idle */ -static int acpi_pad_pur(acpi_handle handle, int *num_cpus) +/* + * Query firmware how many CPUs should be idle + * return -1 on failure + */ +static int acpi_pad_pur(acpi_handle handle) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *package; - int rev, num, ret = -EINVAL; + int num = -1; if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) - return -EINVAL; + return num; if (!buffer.length || !buffer.pointer) - return -EINVAL; + return num; package = buffer.pointer; - if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) - goto out; - rev = package->package.elements[0].integer.value; - num = package->package.elements[1].integer.value; - if (rev != 1 || num < 0) - goto out; - *num_cpus = num; - ret = 0; -out: + + if (package->type == ACPI_TYPE_PACKAGE && + package->package.count == 2 && + package->package.elements[0].integer.value == 1) /* rev 1 */ + + num = package->package.elements[1].integer.value; + kfree(buffer.pointer); - return ret; + return num; } /* Notify firmware how many CPUs are idle */ @@ -433,7 +434,8 @@ static void acpi_pad_handle_notify(acpi_handle handle) uint32_t idle_cpus; mutex_lock(&isolated_cpus_lock); - if (acpi_pad_pur(handle, &num_cpus)) { + num_cpus = acpi_pad_pur(handle); + if (num_cpus < 0) { mutex_unlock(&isolated_cpus_lock); return; } diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index df85b53a674f..7dad9160f209 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -854,6 +854,7 @@ struct acpi_bit_register_info { ACPI_BITMASK_POWER_BUTTON_STATUS | \ ACPI_BITMASK_SLEEP_BUTTON_STATUS | \ ACPI_BITMASK_RT_CLOCK_STATUS | \ + ACPI_BITMASK_PCIEXP_WAKE_DISABLE | \ ACPI_BITMASK_WAKE_STATUS) #define ACPI_BITMASK_TIMER_ENABLE 0x0001 diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 74c24d517f81..4093522eed45 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -109,7 +109,7 @@ void acpi_ex_enter_interpreter(void) * * DESCRIPTION: Reacquire the interpreter execution region from within the * interpreter code. Failure to enter the interpreter region is a - * fatal system error. Used in conjuction with + * fatal system error. Used in conjunction with * relinquish_interpreter * ******************************************************************************/ diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 22cfcfbd9fff..491191e6cf69 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -149,7 +149,7 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) /* * 16-, 32-, and 64-bit cases must use the move macros that perform - * endian conversion and/or accomodate hardware that cannot perform + * endian conversion and/or accommodate hardware that cannot perform * misaligned memory transfers */ case ACPI_RSC_MOVE16: diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 907e350f1c7d..fca34ccfd294 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -34,6 +34,6 @@ config ACPI_APEI_ERST_DEBUG depends on ACPI_APEI help ERST is a way provided by APEI to save and retrieve hardware - error infomation to and from a persistent store. Enable this + error information to and from a persistent store. Enable this if you want to debugging and testing the ERST kernel support and firmware implementation. diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 73fd0c7487c1..4a904a4bf05f 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -445,11 +445,15 @@ EXPORT_SYMBOL_GPL(apei_resources_sub); int apei_resources_request(struct apei_resources *resources, const char *desc) { - struct apei_res *res, *res_bak; + struct apei_res *res, *res_bak = NULL; struct resource *r; + int rc; - apei_resources_sub(resources, &apei_resources_all); + rc = apei_resources_sub(resources, &apei_resources_all); + if (rc) + return rc; + rc = -EINVAL; list_for_each_entry(res, &resources->iomem, list) { r = request_mem_region(res->start, res->end - res->start, desc); @@ -475,7 +479,11 @@ int apei_resources_request(struct apei_resources *resources, } } - apei_resources_merge(&apei_resources_all, resources); + rc = apei_resources_merge(&apei_resources_all, resources); + if (rc) { + pr_err(APEI_PFX "Fail to merge resources!\n"); + goto err_unmap_ioport; + } return 0; err_unmap_ioport: @@ -491,12 +499,13 @@ err_unmap_iomem: break; release_mem_region(res->start, res->end - res->start); } - return -EINVAL; + return rc; } EXPORT_SYMBOL_GPL(apei_resources_request); void apei_resources_release(struct apei_resources *resources) { + int rc; struct apei_res *res; list_for_each_entry(res, &resources->iomem, list) @@ -504,7 +513,9 @@ void apei_resources_release(struct apei_resources *resources) list_for_each_entry(res, &resources->ioport, list) release_region(res->start, res->end - res->start); - apei_resources_sub(&apei_resources_all, resources); + rc = apei_resources_sub(&apei_resources_all, resources); + if (rc) + pr_err(APEI_PFX "Fail to sub resources!\n"); } EXPORT_SYMBOL_GPL(apei_resources_release); diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 465c885938ee..cf29df69380b 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -426,7 +426,9 @@ DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, static int einj_check_table(struct acpi_table_einj *einj_tab) { - if (einj_tab->header_length != sizeof(struct acpi_table_einj)) + if ((einj_tab->header_length != + (sizeof(struct acpi_table_einj) - sizeof(einj_tab->header))) + && (einj_tab->header_length != sizeof(struct acpi_table_einj))) return -EINVAL; if (einj_tab->header.length < sizeof(struct acpi_table_einj)) return -EINVAL; diff --git a/drivers/acpi/apei/erst-dbg.c b/drivers/acpi/apei/erst-dbg.c index 5281ddda2777..da1228a9a544 100644 --- a/drivers/acpi/apei/erst-dbg.c +++ b/drivers/acpi/apei/erst-dbg.c @@ -2,7 +2,7 @@ * APEI Error Record Serialization Table debug support * * ERST is a way provided by APEI to save and retrieve hardware error - * infomation to and from a persistent store. This file provide the + * information to and from a persistent store. This file provide the * debugging/testing support for ERST kernel support and firmware * implementation. * @@ -111,11 +111,13 @@ retry: goto out; } if (len > erst_dbg_buf_len) { - kfree(erst_dbg_buf); + void *p; rc = -ENOMEM; - erst_dbg_buf = kmalloc(len, GFP_KERNEL); - if (!erst_dbg_buf) + p = kmalloc(len, GFP_KERNEL); + if (!p) goto out; + kfree(erst_dbg_buf); + erst_dbg_buf = p; erst_dbg_buf_len = len; goto retry; } @@ -150,11 +152,13 @@ static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, if (mutex_lock_interruptible(&erst_dbg_mutex)) return -EINTR; if (usize > erst_dbg_buf_len) { - kfree(erst_dbg_buf); + void *p; rc = -ENOMEM; - erst_dbg_buf = kmalloc(usize, GFP_KERNEL); - if (!erst_dbg_buf) + p = kmalloc(usize, GFP_KERNEL); + if (!p) goto out; + kfree(erst_dbg_buf); + erst_dbg_buf = p; erst_dbg_buf_len = usize; } rc = copy_from_user(erst_dbg_buf, ubuf, usize); diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 18645f4e83cd..1211c03149e8 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -2,7 +2,7 @@ * APEI Error Record Serialization Table support * * ERST is a way provided by APEI to save and retrieve hardware error - * infomation to and from a persistent store. + * information to and from a persistent store. * * For more information about ERST, please refer to ACPI Specification * version 4.0, section 17.4. @@ -266,13 +266,30 @@ static int erst_exec_move_data(struct apei_exec_context *ctx, { int rc; u64 offset; + void *src, *dst; + + /* ioremap does not work in interrupt context */ + if (in_interrupt()) { + pr_warning(ERST_PFX + "MOVE_DATA can not be used in interrupt context"); + return -EBUSY; + } rc = __apei_exec_read_register(entry, &offset); if (rc) return rc; - memmove((void *)ctx->dst_base + offset, - (void *)ctx->src_base + offset, - ctx->var2); + + src = ioremap(ctx->src_base + offset, ctx->var2); + if (!src) + return -ENOMEM; + dst = ioremap(ctx->dst_base + offset, ctx->var2); + if (!dst) + return -ENOMEM; + + memmove(dst, src, ctx->var2); + + iounmap(src); + iounmap(dst); return 0; } @@ -750,7 +767,9 @@ __setup("erst_disable", setup_erst_disable); static int erst_check_table(struct acpi_table_erst *erst_tab) { - if (erst_tab->header_length != sizeof(struct acpi_table_erst)) + if ((erst_tab->header_length != + (sizeof(struct acpi_table_erst) - sizeof(erst_tab->header))) + && (erst_tab->header_length != sizeof(struct acpi_table_einj))) return -EINVAL; if (erst_tab->header.length < sizeof(struct acpi_table_erst)) return -EINVAL; diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 385a6059714a..0d505e59214d 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -302,7 +302,7 @@ static int __devinit ghes_probe(struct platform_device *ghes_dev) struct ghes *ghes = NULL; int rc = -EINVAL; - generic = ghes_dev->dev.platform_data; + generic = *(struct acpi_hest_generic **)ghes_dev->dev.platform_data; if (!generic->enabled) return -ENODEV; diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c index 343168d18266..1a3508a7fe03 100644 --- a/drivers/acpi/apei/hest.c +++ b/drivers/acpi/apei/hest.c @@ -137,20 +137,23 @@ static int hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void *data) static int hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data) { - struct acpi_hest_generic *generic; struct platform_device *ghes_dev; struct ghes_arr *ghes_arr = data; int rc; if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) return 0; - generic = (struct acpi_hest_generic *)hest_hdr; - if (!generic->enabled) + + if (!((struct acpi_hest_generic *)hest_hdr)->enabled) return 0; ghes_dev = platform_device_alloc("GHES", hest_hdr->source_id); if (!ghes_dev) return -ENOMEM; - ghes_dev->dev.platform_data = generic; + + rc = platform_device_add_data(ghes_dev, &hest_hdr, sizeof(void *)); + if (rc) + goto err; + rc = platform_device_add(ghes_dev); if (rc) goto err; diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c index 8f8bd736d4ff..542e53903891 100644 --- a/drivers/acpi/atomicio.c +++ b/drivers/acpi/atomicio.c @@ -142,7 +142,7 @@ static void __iomem *acpi_pre_map(phys_addr_t paddr, list_add_tail_rcu(&map->list, &acpi_iomaps); spin_unlock_irqrestore(&acpi_iomaps_lock, flags); - return vaddr + (paddr - pg_off); + return map->vaddr + (paddr - map->paddr); err_unmap: iounmap(vaddr); return NULL; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index dc58402b0a17..98417201e9ce 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -273,7 +273,6 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_CYCLE_COUNT, POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 2bb28b9d91c4..af308d03f492 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -183,6 +183,8 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) { printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); acpi_osi_setup("!Windows 2006"); + acpi_osi_setup("!Windows 2006 SP1"); + acpi_osi_setup("!Windows 2006 SP2"); return 0; } static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) @@ -202,6 +204,23 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { + /* + * There have a NVIF method in MSI GX723 DSDT need call by Nvidia + * driver (e.g. nouveau) when user press brightness hotkey. + * Currently, nouveau driver didn't do the job and it causes there + * have a infinite while loop in DSDT when user press hotkey. + * We add MSI GX723's dmi information to this table for workaround + * this issue. + * Will remove MSI GX723 from the table after nouveau grows support. + */ + .callback = dmi_disable_osi_vista, + .ident = "MSI GX723", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"), + DMI_MATCH(DMI_PRODUCT_NAME, "GX723"), + }, + }, + { .callback = dmi_disable_osi_vista, .ident = "Sony VGN-NS10J_S", .matches = { @@ -226,6 +245,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, }, { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba Satellite L355", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Satellite L355"), + }, + }, + { .callback = dmi_disable_osi_win7, .ident = "ASUS K50IJ", .matches = { @@ -233,6 +260,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), }, }, + { + .callback = dmi_disable_osi_vista, + .ident = "Toshiba P305D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 5c221ab535d5..310e3b9749cb 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -55,7 +55,7 @@ EXPORT_SYMBOL(acpi_root_dir); static int set_power_nocheck(const struct dmi_system_id *id) { printk(KERN_NOTICE PREFIX "%s detected - " - "disable power check in power transistion\n", id->ident); + "disable power check in power transition\n", id->ident); acpi_power_nocheck = 1; return 0; } @@ -80,23 +80,15 @@ static int set_copy_dsdt(const struct dmi_system_id *id) static struct dmi_system_id dsdt_dmi_table[] __initdata = { /* - * Insyde BIOS on some TOSHIBA machines corrupt the DSDT. + * Invoke DSDT corruption work-around on all Toshiba Satellite. * https://bugzilla.kernel.org/show_bug.cgi?id=14679 */ { .callback = set_copy_dsdt, - .ident = "TOSHIBA Satellite A505", + .ident = "TOSHIBA Satellite", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A505"), - }, - }, - { - .callback = set_copy_dsdt, - .ident = "TOSHIBA Satellite L505D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L505D"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), }, }, {} @@ -1027,7 +1019,7 @@ static int __init acpi_init(void) /* * If the laptop falls into the DMI check table, the power state check - * will be disabled in the course of device power transistion. + * will be disabled in the course of device power transition. */ dmi_check_system(power_nocheck_dmi_table); diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 8a3b840c0bb2..d94d2953c974 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -369,7 +369,9 @@ static void __exit acpi_fan_exit(void) acpi_bus_unregister_driver(&acpi_fan_driver); +#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); +#endif return; } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1f67057af2a5..3ba8d1f44a73 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -33,7 +33,6 @@ #include <linux/pm_runtime.h> #include <linux/pci.h> #include <linux/pci-acpi.h> -#include <linux/pci-aspm.h> #include <linux/acpi.h> #include <linux/slab.h> #include <acpi/acpi_bus.h> @@ -226,22 +225,31 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle, return status; } -static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) +static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, + u32 support, + u32 *control) { acpi_status status; - u32 support_set, result, capbuf[3]; + u32 result, capbuf[3]; + + support &= OSC_PCI_SUPPORT_MASKS; + support |= root->osc_support_set; - /* do _OSC query for all possible controls */ - support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - capbuf[OSC_SUPPORT_TYPE] = support_set; - capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + capbuf[OSC_SUPPORT_TYPE] = support; + if (control) { + *control &= OSC_PCI_CONTROL_MASKS; + capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; + } else { + /* Run _OSC query for all possible controls. */ + capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); if (ACPI_SUCCESS(status)) { - root->osc_support_set = support_set; - root->osc_control_qry = result; - root->osc_queried = 1; + root->osc_support_set = support; + if (control) + *control = result; } return status; } @@ -255,7 +263,7 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) if (ACPI_FAILURE(status)) return status; mutex_lock(&osc_lock); - status = acpi_pci_query_osc(root, flags); + status = acpi_pci_query_osc(root, flags, NULL); mutex_unlock(&osc_lock); return status; } @@ -365,55 +373,70 @@ out: EXPORT_SYMBOL_GPL(acpi_get_pci_dev); /** - * acpi_pci_osc_control_set - commit requested control to Firmware - * @handle: acpi_handle for the target ACPI object - * @flags: driver's requested control bits + * acpi_pci_osc_control_set - Request control of PCI root _OSC features. + * @handle: ACPI handle of a PCI root bridge (or PCIe Root Complex). + * @mask: Mask of _OSC bits to request control of, place to store control mask. + * @req: Mask of _OSC bits the control of is essential to the caller. + * + * Run _OSC query for @mask and if that is successful, compare the returned + * mask of control bits with @req. If all of the @req bits are set in the + * returned mask, run _OSC request for it. * - * Attempt to take control from Firmware on requested control bits. + * The variable at the @mask address may be modified regardless of whether or + * not the function returns success. On success it will contain the mask of + * _OSC bits the BIOS has granted control of, but its contents are meaningless + * on failure. **/ -acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) +acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 *mask, u32 req) { + struct acpi_pci_root *root; acpi_status status; - u32 control_req, result, capbuf[3]; + u32 ctrl, capbuf[3]; acpi_handle tmp; - struct acpi_pci_root *root; - status = acpi_get_handle(handle, "_OSC", &tmp); - if (ACPI_FAILURE(status)) - return status; + if (!mask) + return AE_BAD_PARAMETER; - control_req = (flags & OSC_PCI_CONTROL_MASKS); - if (!control_req) + ctrl = *mask & OSC_PCI_CONTROL_MASKS; + if ((ctrl & req) != req) return AE_TYPE; root = acpi_pci_find_root(handle); if (!root) return AE_NOT_EXIST; + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return status; + mutex_lock(&osc_lock); + + *mask = ctrl | root->osc_control_set; /* No need to evaluate _OSC if the control was already granted. */ - if ((root->osc_control_set & control_req) == control_req) + if ((root->osc_control_set & ctrl) == ctrl) goto out; - /* Need to query controls first before requesting them */ - if (!root->osc_queried) { - status = acpi_pci_query_osc(root, root->osc_support_set); + /* Need to check the available controls bits before requesting them. */ + while (*mask) { + status = acpi_pci_query_osc(root, root->osc_support_set, mask); if (ACPI_FAILURE(status)) goto out; + if (ctrl == *mask) + break; + ctrl = *mask; } - if ((root->osc_control_qry & control_req) != control_req) { - printk(KERN_DEBUG - "Firmware did not grant requested _OSC control\n"); + + if ((ctrl & req) != req) { status = AE_SUPPORT; goto out; } capbuf[OSC_QUERY_TYPE] = 0; capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; - capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; - status = acpi_pci_run_osc(handle, capbuf, &result); + capbuf[OSC_CONTROL_TYPE] = ctrl; + status = acpi_pci_run_osc(handle, capbuf, mask); if (ACPI_SUCCESS(status)) - root->osc_control_set = result; + root->osc_control_set = *mask; out: mutex_unlock(&osc_lock); return status; @@ -544,14 +567,6 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) if (flags != base_flags) acpi_pci_osc_support(root, flags); - status = acpi_pci_osc_control_set(root->device->handle, - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - - if (ACPI_FAILURE(status)) { - printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n"); - pcie_no_aspm(); - } - pci_acpi_add_bus_pm_notifier(device, root->bus); if (device->wakeup.flags.run_wake) device_set_run_wake(root->bus->bridge, true); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e9699aaed109..bec561c14beb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -29,12 +29,6 @@ static int set_no_mwait(const struct dmi_system_id *id) static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { { - set_no_mwait, "IFL91 board", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), - DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, - { set_no_mwait, "Extensa 5220", { DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -352,4 +346,5 @@ void __init acpi_early_processor_set_pdc(void) acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); + acpi_get_devices("ACPI0007", early_init_pdc, NULL, NULL); } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 156021892389..347eb21b2353 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -850,7 +850,7 @@ static int __init acpi_processor_init(void) printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", acpi_idle_driver.name); } else { - printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s", + printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s\n", cpuidle_get_driver()->name); } diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index ba1bd263d903..3a73a93596e8 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -447,8 +447,8 @@ int acpi_processor_notify_smm(struct module *calling_module) if (!try_module_get(calling_module)) return -EINVAL; - /* is_done is set to negative if an error occured, - * and to postitive if _no_ error occured, but SMM + /* is_done is set to negative if an error occurred, + * and to postitive if _no_ error occurred, but SMM * was already notified. This avoids double notification * which might lead to unexpected results... */ diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index cf82989ae756..4754ff6e70e6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -363,6 +363,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) return 0; } +static int __init init_nvs_nosave(const struct dmi_system_id *d) +{ + acpi_nvs_nosave(); + return 0; +} + static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { .callback = init_old_suspend_ordering, @@ -397,6 +403,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), }, }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Everex StepNote Series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 68e2e4582fa2..f8588f81048a 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -100,7 +100,7 @@ static const struct acpi_dlevel acpi_debug_levels[] = { ACPI_DEBUG_INIT(ACPI_LV_EVENTS), }; -static int param_get_debug_layer(char *buffer, struct kernel_param *kp) +static int param_get_debug_layer(char *buffer, const struct kernel_param *kp) { int result = 0; int i; @@ -128,7 +128,7 @@ static int param_get_debug_layer(char *buffer, struct kernel_param *kp) return result; } -static int param_get_debug_level(char *buffer, struct kernel_param *kp) +static int param_get_debug_level(char *buffer, const struct kernel_param *kp) { int result = 0; int i; @@ -149,10 +149,18 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) return result; } -module_param_call(debug_layer, param_set_uint, param_get_debug_layer, - &acpi_dbg_layer, 0644); -module_param_call(debug_level, param_set_uint, param_get_debug_level, - &acpi_dbg_level, 0644); +static struct kernel_param_ops param_ops_debug_layer = { + .set = param_set_uint, + .get = param_get_debug_layer, +}; + +static struct kernel_param_ops param_ops_debug_level = { + .set = param_set_uint, + .get = param_get_debug_level, +}; + +module_param_cb(debug_layer, ¶m_ops_debug_layer, &acpi_dbg_layer, 0644); +module_param_cb(debug_level, ¶m_ops_debug_level, &acpi_dbg_level, 0644); static char trace_method_name[6]; module_param_string(trace_method_name, trace_method_name, 6, 0644); diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index c5fef01b3c95..b83676126598 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -59,8 +59,8 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, "support\n")); *cap |= ACPI_VIDEO_BACKLIGHT; if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy))) - printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness " - "control misses _BQC function\n"); + printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, " + "cannot determine initial brightness\n"); /* We have backlight support, no need to scan further */ return AE_CTRL_TERMINATE; } diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 65e3e2708371..11ec911016c6 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -828,6 +828,7 @@ config PATA_SAMSUNG_CF config PATA_WINBOND_VLB tristate "Winbond W83759A VLB PATA support (Experimental)" depends on ISA && EXPERIMENTAL + select PATA_LEGACY help Support for the Winbond W83759A controller on Vesa Local Bus systems. diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 158eaa961b1e..d5df04a395ca 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -89,7 +89,6 @@ obj-$(CONFIG_PATA_QDI) += pata_qdi.o obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o obj-$(CONFIG_PATA_SAMSUNG_CF) += pata_samsung_cf.o -obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o obj-$(CONFIG_PATA_PXA) += pata_pxa.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index fe75d8befc3a..99d0e5a51148 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -60,6 +60,7 @@ enum board_ids { board_ahci, board_ahci_ign_iferr, board_ahci_nosntf, + board_ahci_yes_fbs, /* board IDs for specific chipsets in alphabetical order */ board_ahci_mcp65, @@ -89,6 +90,10 @@ static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); static int ahci_pci_device_resume(struct pci_dev *pdev); #endif +static struct scsi_host_template ahci_sht = { + AHCI_SHT("ahci"), +}; + static struct ata_port_operations ahci_vt8251_ops = { .inherits = &ahci_ops, .hardreset = ahci_vt8251_hardreset, @@ -132,6 +137,14 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + [board_ahci_yes_fbs] = + { + AHCI_HFLAGS (AHCI_HFLAG_YES_FBS), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, /* by chipsets */ [board_ahci_mcp65] = { @@ -244,6 +257,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */ { PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */ { PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */ + { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ + { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -362,6 +378,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* Marvell */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ + { PCI_DEVICE(0x1b4b, 0x9123), + .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ /* Promise */ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 7113c5724471..e5fdeebf9ef0 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -209,6 +209,7 @@ enum { link offline */ AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */ AHCI_HFLAG_NO_FPDMA_AA = (1 << 13), /* no FPDMA AA */ + AHCI_HFLAG_YES_FBS = (1 << 14), /* force FBS cap on */ /* ap->flags bits */ @@ -297,7 +298,17 @@ struct ahci_host_priv { extern int ahci_ignore_sss; -extern struct scsi_host_template ahci_sht; +extern struct device_attribute *ahci_shost_attrs[]; +extern struct device_attribute *ahci_sdev_attrs[]; + +#define AHCI_SHT(drv_name) \ + ATA_NCQ_SHT(drv_name), \ + .can_queue = AHCI_MAX_CMDS - 1, \ + .sg_tablesize = AHCI_MAX_SG, \ + .dma_boundary = AHCI_DMA_BOUNDARY, \ + .shost_attrs = ahci_shost_attrs, \ + .sdev_attrs = ahci_sdev_attrs + extern struct ata_port_operations ahci_ops; void ahci_save_initial_config(struct device *dev, diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 4e97f33cca44..84b643270e7a 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -23,6 +23,10 @@ #include <linux/ahci_platform.h> #include "ahci.h" +static struct scsi_host_template ahci_platform_sht = { + AHCI_SHT("ahci_platform"), +}; + static int __init ahci_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -145,7 +149,7 @@ static int __init ahci_probe(struct platform_device *pdev) ahci_print_info(host, "platform"); rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, - &ahci_sht); + &ahci_platform_sht); if (rc) goto err0; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 3971bc0a4838..d712675d0a96 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -302,6 +302,10 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x1c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (CPT) */ { 0x8086, 0x1c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PBG) */ + { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (PBG) */ + { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, { } /* terminate list */ }; diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 81e772a94d59..8eea309ea212 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -121,7 +121,7 @@ static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO, ahci_read_em_buffer, ahci_store_em_buffer); -static struct device_attribute *ahci_shost_attrs[] = { +struct device_attribute *ahci_shost_attrs[] = { &dev_attr_link_power_management_policy, &dev_attr_em_message_type, &dev_attr_em_message, @@ -132,22 +132,14 @@ static struct device_attribute *ahci_shost_attrs[] = { &dev_attr_em_buffer, NULL }; +EXPORT_SYMBOL_GPL(ahci_shost_attrs); -static struct device_attribute *ahci_sdev_attrs[] = { +struct device_attribute *ahci_sdev_attrs[] = { &dev_attr_sw_activity, &dev_attr_unload_heads, NULL }; - -struct scsi_host_template ahci_sht = { - ATA_NCQ_SHT("ahci"), - .can_queue = AHCI_MAX_CMDS - 1, - .sg_tablesize = AHCI_MAX_SG, - .dma_boundary = AHCI_DMA_BOUNDARY, - .shost_attrs = ahci_shost_attrs, - .sdev_attrs = ahci_sdev_attrs, -}; -EXPORT_SYMBOL_GPL(ahci_sht); +EXPORT_SYMBOL_GPL(ahci_sdev_attrs); struct ata_port_operations ahci_ops = { .inherits = &sata_pmp_port_ops, @@ -430,6 +422,12 @@ void ahci_save_initial_config(struct device *dev, cap &= ~HOST_CAP_SNTF; } + if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) { + dev_printk(KERN_INFO, dev, + "controller can do FBS, turning on CAP_FBS\n"); + cap |= HOST_CAP_FBS; + } + if (force_port_map && port_map != force_port_map) { dev_printk(KERN_INFO, dev, "forcing port_map 0x%x -> 0x%x\n", port_map, force_port_map); @@ -1320,7 +1318,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, /* issue the first D2H Register FIS */ msecs = 0; now = jiffies; - if (time_after(now, deadline)) + if (time_after(deadline, now)) msecs = jiffies_to_msecs(deadline - now); tf.ctl |= ATA_SRST; @@ -2036,9 +2034,15 @@ static int ahci_port_start(struct ata_port *ap) u32 cmd = readl(port_mmio + PORT_CMD); if (cmd & PORT_CMD_FBSCP) pp->fbs_supported = true; - else + else if (hpriv->flags & AHCI_HFLAG_YES_FBS) { + dev_printk(KERN_INFO, dev, + "port %d can do FBS, forcing FBSCP\n", + ap->port_no); + pp->fbs_supported = true; + } else dev_printk(KERN_WARNING, dev, - "The port is not capable of FBS\n"); + "port %d is not capable of FBS\n", + ap->port_no); } if (pp->fbs_supported) { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 7ef7c4f216fa..932eaee50245 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5111,15 +5111,18 @@ void ata_qc_issue(struct ata_queued_cmd *qc) qc->flags |= ATA_QCFLAG_ACTIVE; ap->qc_active |= 1 << qc->tag; - /* We guarantee to LLDs that they will have at least one + /* + * We guarantee to LLDs that they will have at least one * non-zero sg if the command is a data command. */ - BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes)); + if (WARN_ON_ONCE(ata_is_data(prot) && + (!qc->sg || !qc->n_elem || !qc->nbytes))) + goto sys_err; if (ata_is_dma(prot) || (ata_is_pio(prot) && (ap->flags & ATA_FLAG_PIO_DMA))) if (ata_sg_setup(qc)) - goto sg_err; + goto sys_err; /* if device is sleeping, schedule reset and abort the link */ if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) { @@ -5136,7 +5139,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc) goto err; return; -sg_err: +sys_err: qc->err_mask |= AC_ERR_SYSTEM; err: ata_qc_complete(qc); @@ -5415,6 +5418,7 @@ static int ata_host_request_pm(struct ata_host *host, pm_message_t mesg, */ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) { + unsigned int ehi_flags = ATA_EHI_QUIET; int rc; /* @@ -5423,7 +5427,18 @@ int ata_host_suspend(struct ata_host *host, pm_message_t mesg) */ ata_lpm_enable(host); - rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1); + /* + * On some hardware, device fails to respond after spun down + * for suspend. As the device won't be used before being + * resumed, we don't need to touch the device. Ask EH to skip + * the usual stuff and proceed directly to suspend. + * + * http://thread.gmane.org/gmane.linux.ide/46764 + */ + if (mesg.event == PM_EVENT_SUSPEND) + ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY; + + rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1); if (rc == 0) host->dev->power.power_state = mesg; return rc; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c9ae299b8342..e48302eae55f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3235,6 +3235,10 @@ static int ata_eh_skip_recovery(struct ata_link *link) if (link->flags & ATA_LFLAG_DISABLED) return 1; + /* skip if explicitly requested */ + if (ehc->i.flags & ATA_EHI_NO_RECOVERY) + return 1; + /* thaw frozen port and recover failed devices */ if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link)) return 0; diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 674c1436491f..e30c537cce32 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -418,6 +418,7 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) if (ioaddr->ctl_addr) iowrite8(tf->ctl, ioaddr->ctl_addr); ap->last_ctl = tf->ctl; + ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { @@ -453,6 +454,8 @@ void ata_sff_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) iowrite8(tf->device, ioaddr->device_addr); VPRINTK("device 0x%X\n", tf->device); } + + ata_wait_idle(ap); } EXPORT_SYMBOL_GPL(ata_sff_tf_load); @@ -1042,7 +1045,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc, u8 status, int in_wq) { - struct ata_eh_info *ehi = &ap->link.eh_info; + struct ata_link *link = qc->dev->link; + struct ata_eh_info *ehi = &link->eh_info; unsigned long flags = 0; int poll_next; @@ -1298,8 +1302,14 @@ fsm_start: } EXPORT_SYMBOL_GPL(ata_sff_hsm_move); -void ata_sff_queue_pio_task(struct ata_port *ap, unsigned long delay) +void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay) { + struct ata_port *ap = link->ap; + + WARN_ON((ap->sff_pio_task_link != NULL) && + (ap->sff_pio_task_link != link)); + ap->sff_pio_task_link = link; + /* may fail if ata_sff_flush_pio_task() in progress */ queue_delayed_work(ata_sff_wq, &ap->sff_pio_task, msecs_to_jiffies(delay)); @@ -1321,14 +1331,18 @@ static void ata_sff_pio_task(struct work_struct *work) { struct ata_port *ap = container_of(work, struct ata_port, sff_pio_task.work); + struct ata_link *link = ap->sff_pio_task_link; struct ata_queued_cmd *qc; u8 status; int poll_next; + BUG_ON(ap->sff_pio_task_link == NULL); /* qc can be NULL if timeout occurred */ - qc = ata_qc_from_tag(ap, ap->link.active_tag); - if (!qc) + qc = ata_qc_from_tag(ap, link->active_tag); + if (!qc) { + ap->sff_pio_task_link = NULL; return; + } fsm_start: WARN_ON_ONCE(ap->hsm_task_state == HSM_ST_IDLE); @@ -1345,11 +1359,16 @@ fsm_start: msleep(2); status = ata_sff_busy_wait(ap, ATA_BUSY, 10); if (status & ATA_BUSY) { - ata_sff_queue_pio_task(ap, ATA_SHORT_PAUSE); + ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE); return; } } + /* + * hsm_move() may trigger another command to be processed. + * clean the link beforehand. + */ + ap->sff_pio_task_link = NULL; /* move the HSM */ poll_next = ata_sff_hsm_move(ap, qc, status, 1); @@ -1376,6 +1395,7 @@ fsm_start: unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + struct ata_link *link = qc->dev->link; /* Use polling pio if the LLD doesn't handle * interrupt driven pio and atapi CDB interrupt. @@ -1396,7 +1416,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST_LAST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_sff_queue_pio_task(ap, 0); + ata_sff_queue_pio_task(link, 0); break; @@ -1409,7 +1429,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc) if (qc->tf.flags & ATA_TFLAG_WRITE) { /* PIO data out protocol */ ap->hsm_task_state = HSM_ST_FIRST; - ata_sff_queue_pio_task(ap, 0); + ata_sff_queue_pio_task(link, 0); /* always send first data block using the * ata_sff_pio_task() codepath. @@ -1419,7 +1439,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc) ap->hsm_task_state = HSM_ST; if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_sff_queue_pio_task(ap, 0); + ata_sff_queue_pio_task(link, 0); /* if polling, ata_sff_pio_task() handles the * rest. otherwise, interrupt handler takes @@ -1441,7 +1461,7 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) || (qc->tf.flags & ATA_TFLAG_POLLING)) - ata_sff_queue_pio_task(ap, 0); + ata_sff_queue_pio_task(link, 0); break; default: @@ -2734,10 +2754,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_dumb_qc_prep); unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - - /* see ata_dma_blacklisted() */ - BUG_ON((ap->flags & ATA_FLAG_PIO_POLLING) && - qc->tf.protocol == ATAPI_PROT_DMA); + struct ata_link *link = qc->dev->link; /* defer PIO handling to sff_qc_issue */ if (!ata_is_dma(qc->tf.protocol)) @@ -2766,7 +2783,7 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc) /* send cdb by polling if no cdb interrupt */ if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) - ata_sff_queue_pio_task(ap, 0); + ata_sff_queue_pio_task(link, 0); break; default: diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index ba43f0f8c880..2215632e4b31 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -74,7 +74,8 @@ static int artop6260_pre_reset(struct ata_link *link, unsigned long deadline) struct pci_dev *pdev = to_pci_dev(ap->host->dev); /* Odd numbered device ids are the units with enable bits (the -R cards) */ - if (pdev->device % 1 && !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) + if ((pdev->device & 1) && + !pci_test_config_bits(pdev, &artop_enable_bits[ap->port_no])) return -ENOENT; return ata_sff_prereset(link, deadline); diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 9f5da1c7454b..905ff76d3cbb 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -121,14 +121,8 @@ static void cmd64x_set_timing(struct ata_port *ap, struct ata_device *adev, u8 m if (pair) { struct ata_timing tp; - ata_timing_compute(pair, pair->pio_mode, &tp, T, 0); ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP); - if (pair->dma_mode) { - ata_timing_compute(pair, pair->dma_mode, - &tp, T, 0); - ata_timing_merge(&tp, &t, &t, ATA_TIMING_SETUP); - } } } diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 9df1ff7e1eaa..eaf194138f21 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -44,6 +44,9 @@ * Specific support is included for the ht6560a/ht6560b/opti82c611a/ * opti82c465mv/promise 20230c/20630/qdi65x0/winbond83759A * + * Support for the Winbond 83759A when operating in advanced mode. + * Multichip mode is not currently supported. + * * Use the autospeed and pio_mask options with: * Appian ADI/2 aka CLPD7220 or AIC25VL01. * Use the jumpers, autospeed and set pio_mask to the mode on the jumpers with @@ -135,12 +138,18 @@ static int ht6560b; /* HT 6560A on primary 1, second 2, both 3 */ static int opti82c611a; /* Opti82c611A on primary 1, sec 2, both 3 */ static int opti82c46x; /* Opti 82c465MV present(pri/sec autodetect) */ static int qdi; /* Set to probe QDI controllers */ -static int winbond; /* Set to probe Winbond controllers, - give I/O port if non standard */ static int autospeed; /* Chip present which snoops speed changes */ static int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */ static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */ +#ifdef PATA_WINBOND_VLB_MODULE +static int winbond = 1; /* Set to probe Winbond controllers, + give I/O port if non standard */ +#else +static int winbond; /* Set to probe Winbond controllers, + give I/O port if non standard */ +#endif + /** * legacy_probe_add - Add interface to probe list * @port: Controller port @@ -1297,6 +1306,7 @@ MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("low-level driver for legacy ATA"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +MODULE_ALIAS("pata_winbond"); module_param(probe_all, int, 0); module_param(autospeed, int, 0); @@ -1305,6 +1315,7 @@ module_param(ht6560b, int, 0); module_param(opti82c611a, int, 0); module_param(opti82c46x, int, 0); module_param(qdi, int, 0); +module_param(winbond, int, 0); module_param(pio_mask, int, 0); module_param(iordy_mask, int, 0); diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 5e659885de16..ac8d7d97e408 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -417,6 +417,8 @@ static void via_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) tf->lbam, tf->lbah); } + + ata_wait_idle(ap); } static int via_port_start(struct ata_port *ap) diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c deleted file mode 100644 index 6d8619b6f670..000000000000 --- a/drivers/ata/pata_winbond.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * pata_winbond.c - Winbond VLB ATA controllers - * (C) 2006 Red Hat - * - * Support for the Winbond 83759A when operating in advanced mode. - * Multichip mode is not currently supported. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/blkdev.h> -#include <linux/delay.h> -#include <scsi/scsi_host.h> -#include <linux/libata.h> -#include <linux/platform_device.h> - -#define DRV_NAME "pata_winbond" -#define DRV_VERSION "0.0.3" - -#define NR_HOST 4 /* Two winbond controllers, two channels each */ - -struct winbond_data { - unsigned long config; - struct platform_device *platform_dev; -}; - -static struct ata_host *winbond_host[NR_HOST]; -static struct winbond_data winbond_data[NR_HOST]; -static int nr_winbond_host; - -#ifdef MODULE -static int probe_winbond = 1; -#else -static int probe_winbond; -#endif - -static DEFINE_SPINLOCK(winbond_lock); - -static void winbond_writecfg(unsigned long port, u8 reg, u8 val) -{ - unsigned long flags; - spin_lock_irqsave(&winbond_lock, flags); - outb(reg, port + 0x01); - outb(val, port + 0x02); - spin_unlock_irqrestore(&winbond_lock, flags); -} - -static u8 winbond_readcfg(unsigned long port, u8 reg) -{ - u8 val; - - unsigned long flags; - spin_lock_irqsave(&winbond_lock, flags); - outb(reg, port + 0x01); - val = inb(port + 0x02); - spin_unlock_irqrestore(&winbond_lock, flags); - - return val; -} - -static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev) -{ - struct ata_timing t; - struct winbond_data *winbond = ap->host->private_data; - int active, recovery; - u8 reg; - int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2); - - reg = winbond_readcfg(winbond->config, 0x81); - - /* Get the timing data in cycles */ - if (reg & 0x40) /* Fast VLB bus, assume 50MHz */ - ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); - else - ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000); - - active = (clamp_val(t.active, 3, 17) - 1) & 0x0F; - recovery = (clamp_val(t.recover, 1, 15) + 1) & 0x0F; - timing = (active << 4) | recovery; - winbond_writecfg(winbond->config, timing, reg); - - /* Load the setup timing */ - - reg = 0x35; - if (adev->class != ATA_DEV_ATA) - reg |= 0x08; /* FIFO off */ - if (!ata_pio_need_iordy(adev)) - reg |= 0x02; /* IORDY off */ - reg |= (clamp_val(t.setup, 0, 3) << 6); - winbond_writecfg(winbond->config, timing + 1, reg); -} - - -static unsigned int winbond_data_xfer(struct ata_device *dev, - unsigned char *buf, unsigned int buflen, int rw) -{ - struct ata_port *ap = dev->link->ap; - int slop = buflen & 3; - - if (ata_id_has_dword_io(dev->id)) { - if (rw == READ) - ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); - else - iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2); - - if (unlikely(slop)) { - __le32 pad; - if (rw == READ) { - pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr)); - memcpy(buf + buflen - slop, &pad, slop); - } else { - memcpy(&pad, buf + buflen - slop, slop); - iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr); - } - buflen += 4 - slop; - } - } else - buflen = ata_sff_data_xfer(dev, buf, buflen, rw); - - return buflen; -} - -static struct scsi_host_template winbond_sht = { - ATA_PIO_SHT(DRV_NAME), -}; - -static struct ata_port_operations winbond_port_ops = { - .inherits = &ata_sff_port_ops, - .sff_data_xfer = winbond_data_xfer, - .cable_detect = ata_cable_40wire, - .set_piomode = winbond_set_piomode, -}; - -/** - * winbond_init_one - attach a winbond interface - * @type: Type to display - * @io: I/O port start - * @irq: interrupt line - * @fast: True if on a > 33Mhz VLB - * - * Register a VLB bus IDE interface. Such interfaces are PIO and we - * assume do not support IRQ sharing. - */ - -static __init int winbond_init_one(unsigned long port) -{ - struct platform_device *pdev; - u8 reg; - int i, rc; - - reg = winbond_readcfg(port, 0x81); - reg |= 0x80; /* jumpered mode off */ - winbond_writecfg(port, 0x81, reg); - reg = winbond_readcfg(port, 0x83); - reg |= 0xF0; /* local control */ - winbond_writecfg(port, 0x83, reg); - reg = winbond_readcfg(port, 0x85); - reg |= 0xF0; /* programmable timing */ - winbond_writecfg(port, 0x85, reg); - - reg = winbond_readcfg(port, 0x81); - - if (!(reg & 0x03)) /* Disabled */ - return -ENODEV; - - for (i = 0; i < 2 ; i ++) { - unsigned long cmd_port = 0x1F0 - (0x80 * i); - unsigned long ctl_port = cmd_port + 0x206; - struct ata_host *host; - struct ata_port *ap; - void __iomem *cmd_addr, *ctl_addr; - - if (!(reg & (1 << i))) - continue; - - pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - rc = -ENOMEM; - host = ata_host_alloc(&pdev->dev, 1); - if (!host) - goto err_unregister; - ap = host->ports[0]; - - rc = -ENOMEM; - cmd_addr = devm_ioport_map(&pdev->dev, cmd_port, 8); - ctl_addr = devm_ioport_map(&pdev->dev, ctl_port, 1); - if (!cmd_addr || !ctl_addr) - goto err_unregister; - - ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port); - - ap->ops = &winbond_port_ops; - ap->pio_mask = ATA_PIO4; - ap->flags |= ATA_FLAG_SLAVE_POSS; - ap->ioaddr.cmd_addr = cmd_addr; - ap->ioaddr.altstatus_addr = ctl_addr; - ap->ioaddr.ctl_addr = ctl_addr; - ata_sff_std_ports(&ap->ioaddr); - - /* hook in a private data structure per channel */ - host->private_data = &winbond_data[nr_winbond_host]; - winbond_data[nr_winbond_host].config = port; - winbond_data[nr_winbond_host].platform_dev = pdev; - - /* activate */ - rc = ata_host_activate(host, 14 + i, ata_sff_interrupt, 0, - &winbond_sht); - if (rc) - goto err_unregister; - - winbond_host[nr_winbond_host++] = dev_get_drvdata(&pdev->dev); - } - - return 0; - - err_unregister: - platform_device_unregister(pdev); - return rc; -} - -/** - * winbond_init - attach winbond interfaces - * - * Attach winbond IDE interfaces by scanning the ports it may occupy. - */ - -static __init int winbond_init(void) -{ - static const unsigned long config[2] = { 0x130, 0x1B0 }; - - int ct = 0; - int i; - - if (probe_winbond == 0) - return -ENODEV; - - /* - * Check both base addresses - */ - - for (i = 0; i < 2; i++) { - if (probe_winbond & (1<<i)) { - int ret = 0; - unsigned long port = config[i]; - - if (request_region(port, 2, "pata_winbond")) { - ret = winbond_init_one(port); - if (ret <= 0) - release_region(port, 2); - else ct+= ret; - } - } - } - if (ct != 0) - return 0; - return -ENODEV; -} - -static __exit void winbond_exit(void) -{ - int i; - - for (i = 0; i < nr_winbond_host; i++) { - ata_host_detach(winbond_host[i]); - release_region(winbond_data[i].config, 2); - platform_device_unregister(winbond_data[i].platform_dev); - } -} - -MODULE_AUTHOR("Alan Cox"); -MODULE_DESCRIPTION("low-level driver for Winbond VL ATA"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_init(winbond_init); -module_exit(winbond_exit); - -module_param(probe_winbond, int, 0); - diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2673a3d14806..6cf57c5c2b5f 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1459,7 +1459,7 @@ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; - u32 dma_chan; + int dma_chan; struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); int err; diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 9463c71dd38e..a9fd9709c262 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1898,19 +1898,25 @@ static void mv_bmdma_start(struct ata_queued_cmd *qc) * LOCKING: * Inherited from caller. */ -static void mv_bmdma_stop(struct ata_queued_cmd *qc) +static void mv_bmdma_stop_ap(struct ata_port *ap) { - struct ata_port *ap = qc->ap; void __iomem *port_mmio = mv_ap_base(ap); u32 cmd; /* clear start/stop bit */ cmd = readl(port_mmio + BMDMA_CMD); - cmd &= ~ATA_DMA_START; - writelfl(cmd, port_mmio + BMDMA_CMD); + if (cmd & ATA_DMA_START) { + cmd &= ~ATA_DMA_START; + writelfl(cmd, port_mmio + BMDMA_CMD); + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_sff_dma_pause(ap); + } +} - /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_sff_dma_pause(ap); +static void mv_bmdma_stop(struct ata_queued_cmd *qc) +{ + mv_bmdma_stop_ap(qc->ap); } /** @@ -1934,8 +1940,21 @@ static u8 mv_bmdma_status(struct ata_port *ap) reg = readl(port_mmio + BMDMA_STATUS); if (reg & ATA_DMA_ACTIVE) status = ATA_DMA_ACTIVE; - else + else if (reg & ATA_DMA_ERR) status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR; + else { + /* + * Just because DMA_ACTIVE is 0 (DMA completed), + * this does _not_ mean the device is "done". + * So we should not yet be signalling ATA_DMA_INTR + * in some cases. Eg. DSM/TRIM, and perhaps others. + */ + mv_bmdma_stop_ap(ap); + if (ioread8(ap->ioaddr.altstatus_addr) & ATA_BUSY) + status = 0; + else + status = ATA_DMA_INTR; + } return status; } @@ -1995,6 +2014,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc) switch (tf->protocol) { case ATA_PROT_DMA: + if (tf->command == ATA_CMD_DSM) + return; + /* fall-thru */ case ATA_PROT_NCQ: break; /* continue below */ case ATA_PROT_PIO: @@ -2094,6 +2116,8 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) if ((tf->protocol != ATA_PROT_DMA) && (tf->protocol != ATA_PROT_NCQ)) return; + if (tf->command == ATA_CMD_DSM) + return; /* use bmdma for this */ /* Fill in Gen IIE command request block */ if (!(tf->flags & ATA_TFLAG_WRITE)) @@ -2260,7 +2284,7 @@ static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc) } if (qc->tf.flags & ATA_TFLAG_POLLING) - ata_sff_queue_pio_task(ap, 0); + ata_sff_queue_pio_task(link, 0); return 0; } @@ -2289,6 +2313,12 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: + if (qc->tf.command == ATA_CMD_DSM) { + if (!ap->ops->bmdma_setup) /* no bmdma on GEN_I */ + return AC_ERR_OTHER; + break; /* use bmdma for this */ + } + /* fall thru */ case ATA_PROT_NCQ: mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index ee9ddeb53417..8cb0347dec28 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -3156,7 +3156,6 @@ static int __devinit ia_init_one(struct pci_dev *pdev, { struct atm_dev *dev; IADEV *iadev; - unsigned long flags; int ret; iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); @@ -3188,19 +3187,14 @@ static int __devinit ia_init_one(struct pci_dev *pdev, ia_dev[iadev_count] = iadev; _ia_dev[iadev_count] = dev; iadev_count++; - spin_lock_init(&iadev->misc_lock); - /* First fixes first. I don't want to think about this now. */ - spin_lock_irqsave(&iadev->misc_lock, flags); if (ia_init(dev) || ia_start(dev)) { IF_INIT(printk("IA register failed!\n");) iadev_count--; ia_dev[iadev_count] = NULL; _ia_dev[iadev_count] = NULL; - spin_unlock_irqrestore(&iadev->misc_lock, flags); ret = -EINVAL; goto err_out_deregister_dev; } - spin_unlock_irqrestore(&iadev->misc_lock, flags); IF_EVENT(printk("iadev_count = %d\n", iadev_count);) iadev->next_board = ia_boards; diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index b2cd20f549cb..077735e0e04b 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -1022,7 +1022,7 @@ typedef struct iadev_t { struct dle_q rx_dle_q; struct free_desc_q *rx_free_desc_qhead; struct sk_buff_head rx_dma_q; - spinlock_t rx_lock, misc_lock; + spinlock_t rx_lock; struct atm_vcc **rx_open; /* list of all open VCs */ u16 num_rx_desc, rx_buf_sz, rxing; u32 rx_pkt_ram, rx_tmp_cnt; diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index f916ddf63938..f46138ab38b6 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -444,6 +444,7 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, struct atm_dev *atmdev = container_of(dev, struct atm_dev, class_dev); struct solos_card *card = atmdev->dev_data; struct sk_buff *skb; + unsigned int len; spin_lock(&card->cli_queue_lock); skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]); @@ -451,11 +452,12 @@ static ssize_t console_show(struct device *dev, struct device_attribute *attr, if(skb == NULL) return sprintf(buf, "No data.\n"); - memcpy(buf, skb->data, skb->len); - dev_dbg(&card->dev->dev, "len: %d\n", skb->len); + len = skb->len; + memcpy(buf, skb->data, len); + dev_dbg(&card->dev->dev, "len: %d\n", len); kfree_skb(skb); - return skb->len; + return len; } static int send_command(struct solos_card *card, int dev, const char *buf, size_t size) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c8a44f5e0584..40af43ebd92d 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -568,7 +568,7 @@ static int _request_firmware(const struct firmware **firmware_p, out: if (retval) { release_firmware(firmware); - firmware_p = NULL; + *firmware_p = NULL; } return retval; diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 5419a49ff135..276d5a701dc3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -59,6 +59,7 @@ void device_pm_init(struct device *dev) { dev->power.status = DPM_ON; init_completion(&dev->power.completion); + complete_all(&dev->power.completion); dev->power.wakeup_count = 0; pm_runtime_init(dev); } diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 31064df1370a..5e4fadcdece9 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -297,6 +297,8 @@ static void enqueue_cmd_and_start_io(ctlr_info_t *h, spin_lock_irqsave(&h->lock, flags); addQ(&h->reqQ, c); h->Qdepth++; + if (h->Qdepth > h->maxQsinceinit) + h->maxQsinceinit = h->Qdepth; start_io(h); spin_unlock_irqrestore(&h->lock, flags); } @@ -4519,6 +4521,12 @@ static __devinit int cciss_kdump_hard_reset_controller(struct pci_dev *pdev) misc_fw_support = readl(&cfgtable->misc_fw_support); use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; + /* The doorbell reset seems to cause lockups on some Smart + * Arrays (e.g. P410, P410i, maybe others). Until this is + * fixed or at least isolated, avoid the doorbell reset. + */ + use_doorbell = 0; + rc = cciss_controller_hard_reset(pdev, vaddr, use_doorbell); if (rc) goto unmap_cfgtable; @@ -4712,6 +4720,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, h->scatter_list = kmalloc(h->max_commands * sizeof(struct scatterlist *), GFP_KERNEL); + if (!h->scatter_list) + goto clean4; + for (k = 0; k < h->nr_cmds; k++) { h->scatter_list[k] = kmalloc(sizeof(struct scatterlist) * h->maxsgentries, @@ -4781,7 +4792,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, clean4: kfree(h->cmd_pool_bits); /* Free up sg elements */ - for (k = 0; k < h->nr_cmds; k++) + for (k-- ; k >= 0; k--) kfree(h->scatter_list[k]); kfree(h->scatter_list); cciss_free_sg_chain_blocks(h->cmd_sg_list, h->nr_cmds); diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index b82c5ce5e9df..76fa3deaee84 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c @@ -974,8 +974,7 @@ static int mg_probe(struct platform_device *plat_dev) host->breq->queuedata = host; /* mflash is random device, thanx for the noop */ - elevator_exit(host->breq->elevator); - err = elevator_init(host->breq, "noop"); + err = elevator_change(host->breq, "noop"); if (err) { printk(KERN_ERR "%s:%d (elevator_init) fail\n", __func__, __LINE__); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 0166ea136045..1b5cfcccd654 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2368,7 +2368,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) pkt_shrink_pktlist(pd); } -static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) +static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor) { if (dev_minor >= MAX_WRITERS) return NULL; diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 126062802cb7..831e75caea3d 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -199,6 +199,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) struct virtio_blk *vblk = disk->private_data; struct request *req; struct bio *bio; + int err; bio = bio_map_kern(vblk->disk->queue, id_str, VIRTIO_BLK_ID_BYTES, GFP_KERNEL); @@ -212,7 +213,10 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str) } req->cmd_type = REQ_TYPE_SPECIAL; - return blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); + err = blk_execute_rq(vblk->disk->queue, vblk->disk, req, false); + blk_put_request(req); + + return err; } static int virtblk_locked_ioctl(struct block_device *bdev, fmode_t mode, diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 0b1eea643262..f2ffc46644df 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -820,7 +820,7 @@ static int blkfront_probe(struct xenbus_device *dev, char *type; int len; /* no unplug has been done: do not hook devices != xen vbds */ - if (xen_platform_pci_unplug & XEN_UNPLUG_IGNORE) { + if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY) { int major; if (!VDEV_IS_EXTENDED(vdevice)) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 710af89b176d..cd18493c9527 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -12,6 +12,7 @@ #include <asm/smp.h> #include "agp.h" #include "intel-agp.h" +#include <linux/intel-gtt.h> #include "intel-gtt.c" @@ -805,6 +806,8 @@ static const struct intel_driver_description { "G45/G43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG, "B43", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG, + "B43", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG, "G41", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, @@ -815,11 +818,19 @@ static const struct intel_driver_description { "HD Graphics", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, "HD Graphics", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, + "Sandybridge", NULL, &intel_gen6_driver }, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, "Sandybridge", NULL, &intel_gen6_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, "Sandybridge", NULL, &intel_gen6_driver }, - { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG, + { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, "Sandybridge", NULL, &intel_gen6_driver }, { 0, 0, NULL, NULL, NULL } }; @@ -1044,6 +1055,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), + ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), { } }; diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 08d47532e605..d09b1ab7e8ab 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -1,6 +1,8 @@ /* * Common Intel AGPGART and GTT definitions. */ +#ifndef _INTEL_AGP_H +#define _INTEL_AGP_H /* Intel registers */ #define INTEL_APSIZE 0xb4 @@ -184,6 +186,8 @@ #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 #define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40 #define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42 +#define PCI_DEVICE_ID_INTEL_B43_1_HB 0x2E90 +#define PCI_DEVICE_ID_INTEL_B43_1_IG 0x2E92 #define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 #define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00 @@ -200,11 +204,16 @@ #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106 -#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_D0_IG 0x0126 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ +#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A /* cover 915 and 945 variants */ #define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \ @@ -231,7 +240,8 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB) #define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB) #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ @@ -244,3 +254,5 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \ IS_SNB) + +#endif diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index d22ffb811bf2..75e0a3497888 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] = .type = INTEL_AGP_CACHED_MEMORY} }; +#define INTEL_AGP_UNCACHED_MEMORY 0 +#define INTEL_AGP_CACHED_MEMORY_LLC 1 +#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 +#define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 +#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 + +static struct gatt_mask intel_gen6_masks[] = +{ + {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED, + .type = INTEL_AGP_UNCACHED_MEMORY }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC, + .type = INTEL_AGP_CACHED_MEMORY_LLC }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT, + .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC, + .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC }, + {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT, + .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT }, +}; + static struct _intel_private { struct pci_dev *pcidev; /* device one */ u8 __iomem *registers; @@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem, off_t pg_start, int mask_type) { int i, j; - u32 cache_bits = 0; - - if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) - { - cache_bits = GEN6_PTE_LLC_MLC; - } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { writel(agp_bridge->driver->mask_memory(agp_bridge, @@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge, return 0; } +static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge, + int type) +{ + unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT; + unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT; + + if (type_mask == AGP_USER_UNCACHED_MEMORY) + return INTEL_AGP_UNCACHED_MEMORY; + else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) + return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT : + INTEL_AGP_CACHED_MEMORY_LLC_MLC; + else /* set 'normal'/'cached' to LLC by default */ + return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT : + INTEL_AGP_CACHED_MEMORY_LLC; +} + + static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, int type) { @@ -588,8 +618,7 @@ static void intel_i830_init_gtt_entries(void) gtt_entries = 0; break; } - } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) { + } else if (IS_SNB) { /* * SandyBridge has new memory control reg at 0x50.w */ @@ -1068,11 +1097,11 @@ static void intel_i9xx_setup_flush(void) intel_i915_setup_chipset_flush(); } - if (intel_private.ifp_resource.start) { + if (intel_private.ifp_resource.start) intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); - if (!intel_private.i9xx_flush_page) - dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); - } + if (!intel_private.i9xx_flush_page) + dev_err(&intel_private.pcidev->dev, + "can't ioremap flush page - no chipset flushing\n"); } static int intel_i9xx_configure(void) @@ -1163,7 +1192,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); - if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY && + if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY && mask_type != INTEL_AGP_CACHED_MEMORY) goto out_err; @@ -1333,8 +1362,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr, int type) { - /* Shift high bits down */ - addr |= (addr >> 28) & 0xff; + /* gen6 has bit11-4 for physical addr bit39-32 */ + addr |= (addr >> 28) & 0xff0; /* Type checking must be done elsewhere */ return addr | bridge->driver->masks[type].mask; @@ -1359,6 +1388,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) break; case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB: case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB: + case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB: *gtt_offset = MB(2); pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); @@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .fetch_size = intel_i9xx_fetch_size, .cleanup = intel_i915_cleanup, .mask_memory = intel_gen6_mask_memory, - .masks = intel_i810_masks, + .masks = intel_gen6_masks, .agp_enable = intel_i810_agp_enable, .cache_flush = global_cache_flush, .create_gatt_table = intel_i965_create_gatt_table, @@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = { .agp_alloc_pages = agp_generic_alloc_pages, .agp_destroy_page = agp_generic_destroy_page, .agp_destroy_pages = agp_generic_destroy_pages, - .agp_type_to_mask_type = intel_i830_type_to_mask_type, + .agp_type_to_mask_type = intel_gen6_type_to_mask_type, .chipset_flush = intel_i915_chipset_flush, #ifdef USE_PCI_DMA_API .agp_map_page = intel_agp_map_page, diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index e0249722d25f..f953c96efc86 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c @@ -159,7 +159,7 @@ static void hangcheck_fire(unsigned long data) if (hangcheck_dump_tasks) { printk(KERN_CRIT "Hangcheck: Task state:\n"); #ifdef CONFIG_MAGIC_SYSRQ - handle_sysrq('t', NULL); + handle_sysrq('t'); #endif /* CONFIG_MAGIC_SYSRQ */ } if (hangcheck_reboot) { diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index fa27d1676ee5..3afd62e856eb 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -651,7 +651,7 @@ int hvc_poll(struct hvc_struct *hp) if (sysrq_pressed) continue; } else if (sysrq_pressed) { - handle_sysrq(buf[i], tty); + handle_sysrq(buf[i]); sysrq_pressed = 0; continue; } diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 1f4b6de65a2d..a2bc885ce60a 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -403,7 +403,7 @@ static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len) hp->sysrq = 1; continue; } else if (hp->sysrq) { - handle_sysrq(c, hp->tty); + handle_sysrq(c); hp->sysrq = 0; continue; } diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 1acdb2509511..a3f5e381e746 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -387,7 +387,7 @@ static int n2rng_init_control(struct n2rng *np) static int n2rng_data_read(struct hwrng *rng, u32 *data) { - struct n2rng *np = rng->priv; + struct n2rng *np = (struct n2rng *) rng->priv; unsigned long ra = __pa(&np->test_data); int len; diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 07f3ea38b582..d4b71e8d0d23 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -1650,7 +1650,7 @@ ip2_close( PTTY tty, struct file *pFile ) /* disable DSS reporting */ i2QueueCommands(PTYPE_INLINE, pCh, 100, 4, CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP); - if ( !tty || (tty->termios->c_cflag & HUPCL) ) { + if (tty->termios->c_cflag & HUPCL) { i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN); pCh->dataSetOut &= ~(I2_DTR | I2_RTS); i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25)); @@ -2930,6 +2930,8 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) if ( pCh ) { rc = copy_to_user(argp, pCh, sizeof(i2ChanStr)); + if (rc) + rc = -EFAULT; } else { rc = -ENODEV; } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3822b4f49c84..7bd7c45b53ef 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -305,6 +305,9 @@ static int num_force_kipmid; #ifdef CONFIG_PCI static int pci_registered; #endif +#ifdef CONFIG_ACPI +static int pnp_registered; +#endif #ifdef CONFIG_PPC_OF static int of_registered; #endif @@ -2126,7 +2129,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, { struct acpi_device *acpi_dev; struct smi_info *info; - struct resource *res; + struct resource *res, *res_second; acpi_handle handle; acpi_status status; unsigned long long tmp; @@ -2182,13 +2185,13 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, info->io.addr_data = res->start; info->io.regspacing = DEFAULT_REGSPACING; - res = pnp_get_resource(dev, + res_second = pnp_get_resource(dev, (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? IORESOURCE_IO : IORESOURCE_MEM, 1); - if (res) { - if (res->start > info->io.addr_data) - info->io.regspacing = res->start - info->io.addr_data; + if (res_second) { + if (res_second->start > info->io.addr_data) + info->io.regspacing = res_second->start - info->io.addr_data; } info->io.regsize = DEFAULT_REGSPACING; info->io.regshift = 0; @@ -3359,6 +3362,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_ACPI pnp_register_driver(&ipmi_pnp_driver); + pnp_registered = 1; #endif #ifdef CONFIG_DMI @@ -3526,7 +3530,8 @@ static __exit void cleanup_ipmi_si(void) pci_unregister_driver(&ipmi_pci_driver); #endif #ifdef CONFIG_ACPI - pnp_unregister_driver(&ipmi_pnp_driver); + if (pnp_registered) + pnp_unregister_driver(&ipmi_pnp_driver); #endif #ifdef CONFIG_PPC_OF diff --git a/drivers/char/mem.c b/drivers/char/mem.c index a398ecdbd758..1f528fad3516 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -788,10 +788,11 @@ static const struct file_operations zero_fops = { /* * capabilities for /dev/zero * - permits private mappings, "copies" are taken of the source of zeros + * - no writeback happens */ static struct backing_dev_info zero_bdi = { .name = "char/mem", - .capabilities = BDI_CAP_MAP_COPY, + .capabilities = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK, }; static const struct file_operations full_fops = { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 79c3bc69165a..7c79d243acc9 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1244,6 +1244,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info, } info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); configure_r_port(tty, info, NULL); + mutex_unlock(&info->port.mutex); return 0; } diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index fef80cfcab5c..e63b830c86cc 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -691,8 +691,10 @@ static int open(struct tty_struct *tty, struct file *filp) if (info->port.count == 1) { /* 1st open on this device, init hardware */ retval = startup(info); - if (retval < 0) + if (retval < 0) { + mutex_unlock(&info->port.mutex); goto cleanup; + } } mutex_unlock(&info->port.mutex); retval = block_til_ready(tty, filp, info); diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 878ac0c2cc68..ef31bb81e843 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -18,7 +18,6 @@ #include <linux/interrupt.h> #include <linux/mm.h> #include <linux/fs.h> -#include <linux/tty.h> #include <linux/mount.h> #include <linux/kdev_t.h> #include <linux/major.h> @@ -76,7 +75,7 @@ static int __init sysrq_always_enabled_setup(char *str) __setup("sysrq_always_enabled", sysrq_always_enabled_setup); -static void sysrq_handle_loglevel(int key, struct tty_struct *tty) +static void sysrq_handle_loglevel(int key) { int i; @@ -93,7 +92,7 @@ static struct sysrq_key_op sysrq_loglevel_op = { }; #ifdef CONFIG_VT -static void sysrq_handle_SAK(int key, struct tty_struct *tty) +static void sysrq_handle_SAK(int key) { struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work; schedule_work(SAK_work); @@ -109,7 +108,7 @@ static struct sysrq_key_op sysrq_SAK_op = { #endif #ifdef CONFIG_VT -static void sysrq_handle_unraw(int key, struct tty_struct *tty) +static void sysrq_handle_unraw(int key) { struct kbd_struct *kbd = &kbd_table[fg_console]; @@ -126,7 +125,7 @@ static struct sysrq_key_op sysrq_unraw_op = { #define sysrq_unraw_op (*(struct sysrq_key_op *)NULL) #endif /* CONFIG_VT */ -static void sysrq_handle_crash(int key, struct tty_struct *tty) +static void sysrq_handle_crash(int key) { char *killer = NULL; @@ -141,7 +140,7 @@ static struct sysrq_key_op sysrq_crash_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -static void sysrq_handle_reboot(int key, struct tty_struct *tty) +static void sysrq_handle_reboot(int key) { lockdep_off(); local_irq_enable(); @@ -154,7 +153,7 @@ static struct sysrq_key_op sysrq_reboot_op = { .enable_mask = SYSRQ_ENABLE_BOOT, }; -static void sysrq_handle_sync(int key, struct tty_struct *tty) +static void sysrq_handle_sync(int key) { emergency_sync(); } @@ -165,7 +164,7 @@ static struct sysrq_key_op sysrq_sync_op = { .enable_mask = SYSRQ_ENABLE_SYNC, }; -static void sysrq_handle_show_timers(int key, struct tty_struct *tty) +static void sysrq_handle_show_timers(int key) { sysrq_timer_list_show(); } @@ -176,7 +175,7 @@ static struct sysrq_key_op sysrq_show_timers_op = { .action_msg = "Show clockevent devices & pending hrtimers (no others)", }; -static void sysrq_handle_mountro(int key, struct tty_struct *tty) +static void sysrq_handle_mountro(int key) { emergency_remount(); } @@ -188,7 +187,7 @@ static struct sysrq_key_op sysrq_mountro_op = { }; #ifdef CONFIG_LOCKDEP -static void sysrq_handle_showlocks(int key, struct tty_struct *tty) +static void sysrq_handle_showlocks(int key) { debug_show_all_locks(); } @@ -226,7 +225,7 @@ static void sysrq_showregs_othercpus(struct work_struct *dummy) static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus); -static void sysrq_handle_showallcpus(int key, struct tty_struct *tty) +static void sysrq_handle_showallcpus(int key) { /* * Fall back to the workqueue based printing if the @@ -252,7 +251,7 @@ static struct sysrq_key_op sysrq_showallcpus_op = { }; #endif -static void sysrq_handle_showregs(int key, struct tty_struct *tty) +static void sysrq_handle_showregs(int key) { struct pt_regs *regs = get_irq_regs(); if (regs) @@ -266,7 +265,7 @@ static struct sysrq_key_op sysrq_showregs_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -static void sysrq_handle_showstate(int key, struct tty_struct *tty) +static void sysrq_handle_showstate(int key) { show_state(); } @@ -277,7 +276,7 @@ static struct sysrq_key_op sysrq_showstate_op = { .enable_mask = SYSRQ_ENABLE_DUMP, }; -static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) +static void sysrq_handle_showstate_blocked(int key) { show_state_filter(TASK_UNINTERRUPTIBLE); } @@ -291,7 +290,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = { #ifdef CONFIG_TRACING #include <linux/ftrace.h> -static void sysrq_ftrace_dump(int key, struct tty_struct *tty) +static void sysrq_ftrace_dump(int key) { ftrace_dump(DUMP_ALL); } @@ -305,7 +304,7 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = { #define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL) #endif -static void sysrq_handle_showmem(int key, struct tty_struct *tty) +static void sysrq_handle_showmem(int key) { show_mem(); } @@ -330,7 +329,7 @@ static void send_sig_all(int sig) } } -static void sysrq_handle_term(int key, struct tty_struct *tty) +static void sysrq_handle_term(int key) { send_sig_all(SIGTERM); console_loglevel = 8; @@ -349,7 +348,7 @@ static void moom_callback(struct work_struct *ignored) static DECLARE_WORK(moom_work, moom_callback); -static void sysrq_handle_moom(int key, struct tty_struct *tty) +static void sysrq_handle_moom(int key) { schedule_work(&moom_work); } @@ -361,7 +360,7 @@ static struct sysrq_key_op sysrq_moom_op = { }; #ifdef CONFIG_BLOCK -static void sysrq_handle_thaw(int key, struct tty_struct *tty) +static void sysrq_handle_thaw(int key) { emergency_thaw_all(); } @@ -373,7 +372,7 @@ static struct sysrq_key_op sysrq_thaw_op = { }; #endif -static void sysrq_handle_kill(int key, struct tty_struct *tty) +static void sysrq_handle_kill(int key) { send_sig_all(SIGKILL); console_loglevel = 8; @@ -385,7 +384,7 @@ static struct sysrq_key_op sysrq_kill_op = { .enable_mask = SYSRQ_ENABLE_SIGNAL, }; -static void sysrq_handle_unrt(int key, struct tty_struct *tty) +static void sysrq_handle_unrt(int key) { normalize_rt_tasks(); } @@ -493,7 +492,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p) sysrq_key_table[i] = op_p; } -void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) +void __handle_sysrq(int key, bool check_mask) { struct sysrq_key_op *op_p; int orig_log_level; @@ -520,7 +519,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { printk("%s\n", op_p->action_msg); console_loglevel = orig_log_level; - op_p->handler(key, tty); + op_p->handler(key); } else { printk("This sysrq operation is disabled.\n"); } @@ -545,10 +544,10 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask) spin_unlock_irqrestore(&sysrq_key_table_lock, flags); } -void handle_sysrq(int key, struct tty_struct *tty) +void handle_sysrq(int key) { if (sysrq_on()) - __handle_sysrq(key, tty, 1); + __handle_sysrq(key, true); } EXPORT_SYMBOL(handle_sysrq); @@ -597,7 +596,7 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type, default: if (sysrq_down && value && value != 2) - __handle_sysrq(sysrq_xlate[code], NULL, 1); + __handle_sysrq(sysrq_xlate[code], true); break; } @@ -765,7 +764,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, if (get_user(c, buf)) return -EFAULT; - __handle_sysrq(c, NULL, 0); + __handle_sysrq(c, false); } return count; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 949067a0bd47..613c852ee0fe 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -355,7 +355,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) if (*stp == '\0') stp = NULL; - if (tty_line >= 0 && tty_line <= p->num && p->ops && + if (tty_line >= 0 && tty_line < p->num && p->ops && p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { res = tty_driver_kref_get(p); *line = tty_line; diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 942a9826bd23..c810481a5bc2 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -596,6 +596,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, ssize_t ret; bool nonblock; + /* Userspace could be out to fool us */ + if (!count) + return 0; + port = filp->private_data; nonblock = filp->f_flags & O_NONBLOCK; @@ -642,7 +646,7 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait) poll_wait(filp, &port->waitqueue, wait); ret = 0; - if (port->inbuf) + if (!will_read_block(port)) ret |= POLLIN | POLLRDNORM; if (!will_write_block(port)) ret |= POLLOUT; diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 50590c7f2c01..281aada7b4a1 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -906,22 +906,16 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, * bottom of buffer */ old_origin += (old_rows - new_rows) * old_row_size; - end = vc->vc_scr_end; } else { /* * Cursor is in no man's land, copy 1/2 screenful * from the top and bottom of cursor position */ old_origin += (vc->vc_y - new_rows/2) * old_row_size; - end = old_origin + (old_row_size * new_rows); } - } else - /* - * Cursor near the top, copy contents from the top of buffer - */ - end = (old_rows > new_rows) ? old_origin + - (old_row_size * new_rows) : - vc->vc_scr_end; + } + + end = old_origin + old_row_size * min(old_rows, new_rows); update_attr(vc); @@ -3075,8 +3069,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last, old_was_color = vc->vc_can_do_color; vc->vc_sw->con_deinit(vc); - if (!vc->vc_origin) - vc->vc_origin = (unsigned long)vc->vc_screenbuf; + vc->vc_origin = (unsigned long)vc->vc_screenbuf; visual_init(vc, i, 0); set_origin(vc); update_attr(vc); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 2bbeaaea46e9..38df8c19e74c 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -533,11 +533,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, case KIOCSOUND: if (!perm) goto eperm; - /* FIXME: This is an old broken API but we need to keep it - supported and somehow separate the historic advertised - tick rate from any real one */ + /* + * The use of PIT_TICK_RATE is historic, it used to be + * the platform-dependent CLOCK_TICK_RATE between 2.6.12 + * and 2.6.36, which was a minor but unfortunate ABI + * change. + */ if (arg) - arg = CLOCK_TICK_RATE / arg; + arg = PIT_TICK_RATE / arg; kd_mksound(arg, 0); break; @@ -553,11 +556,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, */ ticks = HZ * ((arg >> 16) & 0xffff) / 1000; count = ticks ? (arg & 0xffff) : 0; - /* FIXME: This is an old broken API but we need to keep it - supported and somehow separate the historic advertised - tick rate from any real one */ if (count) - count = CLOCK_TICK_RATE / count; + count = PIT_TICK_RATE / count; kd_mksound(count, ticks); break; } diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c2408bbe9c2e..f508690eb958 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -80,7 +80,7 @@ * Limiting Performance Impact * --------------------------- * C states, especially those with large exit latencies, can have a real - * noticable impact on workloads, which is not acceptable for most sysadmins, + * noticeable impact on workloads, which is not acceptable for most sysadmins, * and in addition, less performance has a power price of its own. * * As a general rule of thumb, menu assumes that the following heuristic diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 8661c84a105d..b98c67664ae7 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -39,6 +39,10 @@ static DEFINE_SPINLOCK(dca_lock); static LIST_HEAD(dca_domains); +static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); + +static int dca_providers_blocked; + static struct pci_bus *dca_pci_rc_from_dev(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); @@ -70,6 +74,60 @@ static void dca_free_domain(struct dca_domain *domain) kfree(domain); } +static int dca_provider_ioat_ver_3_0(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + return ((pdev->vendor == PCI_VENDOR_ID_INTEL) && + ((pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG0) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG1) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG2) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG3) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG4) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG5) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG6) || + (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_TBG7))); +} + +static void unregister_dca_providers(void) +{ + struct dca_provider *dca, *_dca; + struct list_head unregistered_providers; + struct dca_domain *domain; + unsigned long flags; + + blocking_notifier_call_chain(&dca_provider_chain, + DCA_PROVIDER_REMOVE, NULL); + + INIT_LIST_HEAD(&unregistered_providers); + + spin_lock_irqsave(&dca_lock, flags); + + if (list_empty(&dca_domains)) { + spin_unlock_irqrestore(&dca_lock, flags); + return; + } + + /* at this point only one domain in the list is expected */ + domain = list_first_entry(&dca_domains, struct dca_domain, node); + if (!domain) + return; + + list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) { + list_del(&dca->node); + list_add(&dca->node, &unregistered_providers); + } + + dca_free_domain(domain); + + spin_unlock_irqrestore(&dca_lock, flags); + + list_for_each_entry_safe(dca, _dca, &unregistered_providers, node) { + dca_sysfs_remove_provider(dca); + list_del(&dca->node); + } +} + static struct dca_domain *dca_find_domain(struct pci_bus *rc) { struct dca_domain *domain; @@ -90,9 +148,13 @@ static struct dca_domain *dca_get_domain(struct device *dev) domain = dca_find_domain(rc); if (!domain) { - domain = dca_allocate_domain(rc); - if (domain) - list_add(&domain->node, &dca_domains); + if (dca_provider_ioat_ver_3_0(dev) && !list_empty(&dca_domains)) { + dca_providers_blocked = 1; + } else { + domain = dca_allocate_domain(rc); + if (domain) + list_add(&domain->node, &dca_domains); + } } return domain; @@ -293,8 +355,6 @@ void free_dca_provider(struct dca_provider *dca) } EXPORT_SYMBOL_GPL(free_dca_provider); -static BLOCKING_NOTIFIER_HEAD(dca_provider_chain); - /** * register_dca_provider - register a dca provider * @dca - struct created by alloc_dca_provider() @@ -306,6 +366,13 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev) unsigned long flags; struct dca_domain *domain; + spin_lock_irqsave(&dca_lock, flags); + if (dca_providers_blocked) { + spin_unlock_irqrestore(&dca_lock, flags); + return -ENODEV; + } + spin_unlock_irqrestore(&dca_lock, flags); + err = dca_sysfs_add_provider(dca, dev); if (err) return err; @@ -313,7 +380,13 @@ int register_dca_provider(struct dca_provider *dca, struct device *dev) spin_lock_irqsave(&dca_lock, flags); domain = dca_get_domain(dev); if (!domain) { - spin_unlock_irqrestore(&dca_lock, flags); + if (dca_providers_blocked) { + spin_unlock_irqrestore(&dca_lock, flags); + dca_sysfs_remove_provider(dca); + unregister_dca_providers(); + } else { + spin_unlock_irqrestore(&dca_lock, flags); + } return -ENODEV; } list_add(&dca->node, &domain->dca_providers); diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 216f9d383b5b..effd140fc042 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -879,7 +879,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) dma->device_issue_pending = ioat2_issue_pending; dma->device_alloc_chan_resources = ioat2_alloc_chan_resources; dma->device_free_chan_resources = ioat2_free_chan_resources; - dma->device_tx_status = ioat_tx_status; + dma->device_tx_status = ioat_dma_tx_status; err = ioat_probe(device); if (err) diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 86c5ae9fde34..411d5bf50fc4 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -162,7 +162,7 @@ static int mv_is_err_intr(u32 intr_cause) static void mv_xor_device_clear_eoc_cause(struct mv_xor_chan *chan) { - u32 val = (1 << (1 + (chan->idx * 16))); + u32 val = ~(1 << (chan->idx * 16)); dev_dbg(chan->device->common.dev, "%s, val 0x%08x\n", __func__, val); __raw_writel(val, XOR_INTR_CAUSE(chan)); } diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index fb64cf36ba61..eb6b54dbb806 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -580,7 +580,6 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( sh_chan = to_sh_chan(chan); param = chan->private; - slave_addr = param->config->addr; /* Someone calling slave DMA on a public channel? */ if (!param || !sg_len) { @@ -589,6 +588,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( return NULL; } + slave_addr = param->config->addr; + /* * if (param != NULL), this is a successfully requested slave channel, * therefore param->config != NULL too. diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 670239ab7511..e7d5d6b5dcf6 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2071,16 +2071,6 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, amd64_handle_ce(mci, info); else if (ecc_type == 1) amd64_handle_ue(mci, info); - - /* - * If main error is CE then overflow must be CE. If main error is UE - * then overflow is unknown. We'll call the overflow a CE - if - * panic_on_ue is set then we're already panic'ed and won't arrive - * here. Else, then apparently someone doesn't think that UE's are - * catastrophic. - */ - if (info->nbsh & K8_NBSH_OVERFLOW) - edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR " Error Overflow"); } void amd64_decode_bus_error(int node_id, struct err_regs *regs) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 3630308e7b81..6b21e25f7a84 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -339,6 +339,9 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) { int status; + if (mci->op_state != OP_RUNNING_POLL) + return; + status = cancel_delayed_work(&mci->work); if (status == 0) { debugf0("%s() not canceled, flush the queue\n", diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index bae9351e9473..9014df6f605d 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c @@ -365,11 +365,10 @@ static int amd_decode_mce(struct notifier_block *nb, unsigned long val, pr_emerg("MC%d_STATUS: ", m->bank); - pr_cont("%sorrected error, report: %s, MiscV: %svalid, " + pr_cont("%sorrected error, other errors lost: %s, " "CPU context corrupt: %s", ((m->status & MCI_STATUS_UC) ? "Unc" : "C"), - ((m->status & MCI_STATUS_EN) ? "yes" : "no"), - ((m->status & MCI_STATUS_MISCV) ? "" : "in"), + ((m->status & MCI_STATUS_OVER) ? "yes" : "no"), ((m->status & MCI_STATUS_PCC) ? "yes" : "no")); /* do the two bits[14:13] together */ @@ -426,11 +425,15 @@ static struct notifier_block amd_mce_dec_nb = { static int __init mce_amd_init(void) { /* - * We can decode MCEs for Opteron and later CPUs: + * We can decode MCEs for K8, F10h and F11h CPUs: */ - if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && - (boot_cpu_data.x86 >= 0xf)) - atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb); + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) + return 0; + + if (boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x11) + return 0; + + atomic_notifier_chain_register(&x86_mce_decoder_chain, &amd_mce_dec_nb); return 0; } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index e0187d16dd7c..0fd5b85a0f75 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1140,6 +1140,7 @@ static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = { ATTR_COUNTER(0), ATTR_COUNTER(1), ATTR_COUNTER(2), + { .attr = { .name = NULL } } }; static struct mcidev_sysfs_group i7core_udimm_counters = { diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index ca7ca56661e0..b42a0bde8494 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -81,6 +81,10 @@ static int close_transaction(struct fw_transaction *transaction, spin_lock_irqsave(&card->lock, flags); list_for_each_entry(t, &card->transaction_list, link) { if (t == transaction) { + if (!del_timer(&t->split_timeout_timer)) { + spin_unlock_irqrestore(&card->lock, flags); + goto timed_out; + } list_del_init(&t->link); card->tlabel_mask &= ~(1ULL << t->tlabel); break; @@ -89,11 +93,11 @@ static int close_transaction(struct fw_transaction *transaction, spin_unlock_irqrestore(&card->lock, flags); if (&t->link != &card->transaction_list) { - del_timer_sync(&t->split_timeout_timer); t->callback(card, rcode, NULL, 0, t->callback_data); return 0; } + timed_out: return -ENOENT; } @@ -921,6 +925,10 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) spin_lock_irqsave(&card->lock, flags); list_for_each_entry(t, &card->transaction_list, link) { if (t->node_id == source && t->tlabel == tlabel) { + if (!del_timer(&t->split_timeout_timer)) { + spin_unlock_irqrestore(&card->lock, flags); + goto timed_out; + } list_del_init(&t->link); card->tlabel_mask &= ~(1ULL << t->tlabel); break; @@ -929,6 +937,7 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) spin_unlock_irqrestore(&card->lock, flags); if (&t->link == &card->transaction_list) { + timed_out: fw_notify("Unsolicited response (source %x, tlabel %x)\n", source, tlabel); return; @@ -963,8 +972,6 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) break; } - del_timer_sync(&t->split_timeout_timer); - /* * The response handler may be executed while the request handler * is still pending. Cancel the request handler. diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index da17d409a244..33f8421c71cc 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -579,7 +579,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net, if (!peer) { fw_notify("No peer for ARP packet from %016llx\n", (unsigned long long)peer_guid); - goto failed_proto; + goto no_peer; } /* @@ -656,7 +656,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net, return 0; - failed_proto: + no_peer: net->stats.rx_errors++; net->stats.rx_dropped++; @@ -664,7 +664,7 @@ static int fwnet_finish_incoming_packet(struct net_device *net, if (netif_queue_stopped(net)) netif_wake_queue(net); - return 0; + return -ENOENT; } static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, @@ -701,7 +701,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, fw_error("out of memory\n"); net->stats.rx_dropped++; - return -1; + return -ENOMEM; } skb_reserve(skb, (net->hard_header_len + 15) & ~15); memcpy(skb_put(skb, len), buf, len); @@ -726,8 +726,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, spin_lock_irqsave(&dev->lock, flags); peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation); - if (!peer) - goto bad_proto; + if (!peer) { + retval = -ENOENT; + goto fail; + } pd = fwnet_pd_find(peer, datagram_label); if (pd == NULL) { @@ -741,7 +743,7 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, dg_size, buf, fg_off, len); if (pd == NULL) { retval = -ENOMEM; - goto bad_proto; + goto fail; } peer->pdg_size++; } else { @@ -755,9 +757,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, pd = fwnet_pd_new(net, peer, datagram_label, dg_size, buf, fg_off, len); if (pd == NULL) { - retval = -ENOMEM; peer->pdg_size--; - goto bad_proto; + retval = -ENOMEM; + goto fail; } } else { if (!fwnet_pd_update(peer, pd, buf, fg_off, len)) { @@ -768,7 +770,8 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, */ fwnet_pd_delete(pd); peer->pdg_size--; - goto bad_proto; + retval = -ENOMEM; + goto fail; } } } /* new datagram or add to existing one */ @@ -794,14 +797,13 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, spin_unlock_irqrestore(&dev->lock, flags); return 0; - - bad_proto: + fail: spin_unlock_irqrestore(&dev->lock, flags); if (netif_queue_stopped(net)) netif_wake_queue(net); - return 0; + return retval; } static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 7f03540cabe8..1b05896648bc 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -263,6 +263,7 @@ static const struct { {PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, QUIRK_NO_MSI}, {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_VIA, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, + {PCI_VENDOR_ID_RICOH, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, QUIRK_BE_HEADERS}, }; @@ -694,7 +695,15 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) log_ar_at_event('R', p.speed, p.header, evt); /* - * The OHCI bus reset handler synthesizes a phy packet with + * Several controllers, notably from NEC and VIA, forget to + * write ack_complete status at PHY packet reception. + */ + if (evt == OHCI1394_evt_no_status && + (p.header[0] & 0xff) == (OHCI1394_phy_tcode << 4)) + p.ack = ACK_COMPLETE; + + /* + * The OHCI bus reset handler synthesizes a PHY packet with * the new generation number when a bus reset happens (see * section 8.4.2.3). This helps us determine when a request * was received and make sure we send the response in the same diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 9f76171717e5..bfae4b309791 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -450,7 +450,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, if (&orb->link != &lu->orb_list) { orb->callback(orb, &status); - kref_put(&orb->kref, free_orb); + kref_put(&orb->kref, free_orb); /* orb callback reference */ } else { fw_error("status write for unknown orb\n"); } @@ -472,20 +472,28 @@ static void complete_transaction(struct fw_card *card, int rcode, * So this callback only sets the rcode if it hasn't already * been set and only does the cleanup if the transaction * failed and we didn't already get a status write. + * + * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some + * OXUF936QSE firmwares occasionally respond after Split_Timeout and + * complete the ORB just fine. Note, we also get RCODE_CANCELLED + * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0. */ spin_lock_irqsave(&card->lock, flags); if (orb->rcode == -1) orb->rcode = rcode; - if (orb->rcode != RCODE_COMPLETE) { + + if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) { list_del(&orb->link); spin_unlock_irqrestore(&card->lock, flags); + orb->callback(orb, NULL); + kref_put(&orb->kref, free_orb); /* orb callback reference */ } else { spin_unlock_irqrestore(&card->lock, flags); } - kref_put(&orb->kref, free_orb); + kref_put(&orb->kref, free_orb); /* transaction callback reference */ } static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, @@ -501,9 +509,8 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, list_add_tail(&orb->link, &lu->orb_list); spin_unlock_irqrestore(&device->card->lock, flags); - /* Take a ref for the orb list and for the transaction callback. */ - kref_get(&orb->kref); - kref_get(&orb->kref); + kref_get(&orb->kref); /* transaction callback reference */ + kref_get(&orb->kref); /* orb callback reference */ fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, node_id, generation, device->max_speed, offset, @@ -525,11 +532,11 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) list_for_each_entry_safe(orb, next, &list, link) { retval = 0; - if (fw_cancel_transaction(device->card, &orb->t) == 0) - continue; + fw_cancel_transaction(device->card, &orb->t); orb->rcode = RCODE_CANCELLED; orb->callback(orb, NULL); + kref_put(&orb->kref, free_orb); /* orb callback reference */ } return retval; diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c index b42f42ca70c3..823559ab0e24 100644 --- a/drivers/gpio/sx150x.c +++ b/drivers/gpio/sx150x.c @@ -459,17 +459,33 @@ static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) return err; } -static int sx150x_init_hw(struct sx150x_chip *chip, - struct sx150x_platform_data *pdata) +static int sx150x_reset(struct sx150x_chip *chip) { - int err = 0; + int err; - err = i2c_smbus_write_word_data(chip->client, + err = i2c_smbus_write_byte_data(chip->client, chip->dev_cfg->reg_reset, - 0x3412); + 0x12); if (err < 0) return err; + err = i2c_smbus_write_byte_data(chip->client, + chip->dev_cfg->reg_reset, + 0x34); + return err; +} + +static int sx150x_init_hw(struct sx150x_chip *chip, + struct sx150x_platform_data *pdata) +{ + int err = 0; + + if (pdata->reset_during_probe) { + err = sx150x_reset(chip); + if (err < 0) + return err; + } + err = sx150x_i2c_write(chip->client, chip->dev_cfg->reg_misc, 0x01); diff --git a/drivers/gpu/drm/drm_buffer.c b/drivers/gpu/drm/drm_buffer.c index 55d03ed05000..529a0dbe9fc6 100644 --- a/drivers/gpu/drm/drm_buffer.c +++ b/drivers/gpu/drm/drm_buffer.c @@ -98,8 +98,8 @@ EXPORT_SYMBOL(drm_buffer_alloc); * user_data: A pointer the data that is copied to the buffer. * size: The Number of bytes to copy. */ -extern int drm_buffer_copy_from_user(struct drm_buffer *buf, - void __user *user_data, int size) +int drm_buffer_copy_from_user(struct drm_buffer *buf, + void __user *user_data, int size) { int nr_pages = size / PAGE_SIZE + 1; int idx; @@ -163,7 +163,7 @@ void *drm_buffer_read_object(struct drm_buffer *buf, { int idx = drm_buffer_index(buf); int page = drm_buffer_page(buf); - void *obj = 0; + void *obj = NULL; if (idx + objsize <= PAGE_SIZE) { obj = &buf->data[page][idx]; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 7e31d4348340..dcbeb98f195a 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -34,6 +34,9 @@ #include "drm_crtc_helper.h" #include "drm_fb_helper.h" +static bool drm_kms_helper_poll = true; +module_param_named(poll, drm_kms_helper_poll, bool, 0600); + static void drm_mode_validate_flag(struct drm_connector *connector, int flags) { @@ -99,8 +102,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, connector->status = connector_status_disconnected; if (connector->funcs->force) connector->funcs->force(connector); - } else - connector->status = connector->funcs->detect(connector); + } else { + connector->status = connector->funcs->detect(connector, true); + drm_kms_helper_poll_enable(dev); + } if (connector->status == connector_status_disconnected) { DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", @@ -110,11 +115,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, } count = (*connector_funcs->get_modes)(connector); - if (!count) { + if (count == 0 && connector->status == connector_status_connected) count = drm_add_modes_noedid(connector, 1024, 768); - if (!count) - return 0; - } + if (count == 0) + goto prune; drm_mode_connector_list_update(connector); @@ -633,13 +637,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) mode_changed = true; if (mode_changed) { - old_fb = set->crtc->fb; - set->crtc->fb = set->fb; set->crtc->enabled = (set->mode != NULL); if (set->mode != NULL) { DRM_DEBUG_KMS("attempting to set mode from" " userspace\n"); drm_mode_debug_printmodeline(set->mode); + old_fb = set->crtc->fb; + set->crtc->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, old_fb)) { @@ -840,6 +844,9 @@ static void output_poll_execute(struct work_struct *work) enum drm_connector_status old_status, status; bool repoll = false, changed = false; + if (!drm_kms_helper_poll) + return; + mutex_lock(&dev->mode_config.mutex); list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -859,7 +866,7 @@ static void output_poll_execute(struct work_struct *work) !(connector->polled & DRM_CONNECTOR_POLL_HPD)) continue; - status = connector->funcs->detect(connector); + status = connector->funcs->detect(connector, false); if (old_status != status) changed = true; } @@ -890,6 +897,9 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) bool poll = false; struct drm_connector *connector; + if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) + return; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { if (connector->polled) poll = true; @@ -919,8 +929,10 @@ void drm_helper_hpd_irq_event(struct drm_device *dev) { if (!dev->mode_config.poll_enabled) return; + /* kill timer and schedule immediate execution, this doesn't block */ cancel_delayed_work(&dev->mode_config.output_poll_work); - queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); + if (drm_kms_helper_poll) + queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); } EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 90288ec7c284..84da748555bc 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -55,6 +55,9 @@ static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv); +#define DRM_IOCTL_DEF(ioctl, _func, _flags) \ + [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0} + /** Ioctl table */ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), @@ -421,6 +424,7 @@ long drm_ioctl(struct file *filp, int retcode = -EINVAL; char stack_kdata[128]; char *kdata = NULL; + unsigned int usize, asize; dev = file_priv->minor->dev; atomic_inc(&dev->ioctl_count); @@ -436,11 +440,18 @@ long drm_ioctl(struct file *filp, ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) goto err_i1; if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) && - (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) + (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { + u32 drv_size; ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; + drv_size = _IOC_SIZE(ioctl->cmd_drv); + usize = asize = _IOC_SIZE(cmd); + if (drv_size > asize) + asize = drv_size; + } else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { ioctl = &drm_ioctls[nr]; cmd = ioctl->cmd; + usize = asize = _IOC_SIZE(cmd); } else goto err_i1; @@ -460,10 +471,10 @@ long drm_ioctl(struct file *filp, retcode = -EACCES; } else { if (cmd & (IOC_IN | IOC_OUT)) { - if (_IOC_SIZE(cmd) <= sizeof(stack_kdata)) { + if (asize <= sizeof(stack_kdata)) { kdata = stack_kdata; } else { - kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + kdata = kmalloc(asize, GFP_KERNEL); if (!kdata) { retcode = -ENOMEM; goto err_i1; @@ -473,11 +484,13 @@ long drm_ioctl(struct file *filp, if (cmd & IOC_IN) { if (copy_from_user(kdata, (void __user *)arg, - _IOC_SIZE(cmd)) != 0) { + usize) != 0) { retcode = -EFAULT; goto err_i1; } - } + } else + memset(kdata, 0, usize); + if (ioctl->flags & DRM_UNLOCKED) retcode = func(dev, kdata, file_priv); else { @@ -488,7 +501,7 @@ long drm_ioctl(struct file *filp, if (cmd & IOC_OUT) { if (copy_to_user((void __user *)arg, kdata, - _IOC_SIZE(cmd)) != 0) + usize) != 0) retcode = -EFAULT; } } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index de82e201d682..6a5e403f9aa1 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -94,10 +94,11 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_conn int i; enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; struct drm_fb_helper_cmdline_mode *cmdline_mode; - struct drm_connector *connector = fb_helper_conn->connector; + struct drm_connector *connector; if (!fb_helper_conn) return false; + connector = fb_helper_conn->connector; cmdline_mode = &fb_helper_conn->cmdline_mode; if (!mode_option) @@ -369,7 +370,7 @@ static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) } static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn); -static void drm_fb_helper_sysrq(int dummy1, struct tty_struct *dummy3) +static void drm_fb_helper_sysrq(int dummy1) { schedule_work(&drm_fb_helper_restore_work); } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 3a652a65546f..b744dad5c237 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -41,6 +41,7 @@ /* from BKL pushdown: note that nothing else serializes idr_find() */ DEFINE_MUTEX(drm_global_mutex); +EXPORT_SYMBOL(drm_global_mutex); static int drm_open_helper(struct inode *inode, struct file *filp, struct drm_device * dev); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index bf92d07510df..5663d2719063 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -148,7 +148,7 @@ int drm_gem_object_init(struct drm_device *dev, return -ENOMEM; kref_init(&obj->refcount); - kref_init(&obj->handlecount); + atomic_set(&obj->handle_count, 0); obj->size = size; atomic_inc(&dev->object_count); @@ -462,28 +462,6 @@ drm_gem_object_free(struct kref *kref) } EXPORT_SYMBOL(drm_gem_object_free); -/** - * Called after the last reference to the object has been lost. - * Must be called without holding struct_mutex - * - * Frees the object - */ -void -drm_gem_object_free_unlocked(struct kref *kref) -{ - struct drm_gem_object *obj = (struct drm_gem_object *) kref; - struct drm_device *dev = obj->dev; - - if (dev->driver->gem_free_object_unlocked != NULL) - dev->driver->gem_free_object_unlocked(obj); - else if (dev->driver->gem_free_object != NULL) { - mutex_lock(&dev->struct_mutex); - dev->driver->gem_free_object(obj); - mutex_unlock(&dev->struct_mutex); - } -} -EXPORT_SYMBOL(drm_gem_object_free_unlocked); - static void drm_gem_object_ref_bug(struct kref *list_kref) { BUG(); @@ -496,12 +474,8 @@ static void drm_gem_object_ref_bug(struct kref *list_kref) * called before drm_gem_object_free or we'll be touching * freed memory */ -void -drm_gem_object_handle_free(struct kref *kref) +void drm_gem_object_handle_free(struct drm_gem_object *obj) { - struct drm_gem_object *obj = container_of(kref, - struct drm_gem_object, - handlecount); struct drm_device *dev = obj->dev; /* Remove any name for this object */ @@ -528,6 +502,10 @@ void drm_gem_vm_open(struct vm_area_struct *vma) struct drm_gem_object *obj = vma->vm_private_data; drm_gem_object_reference(obj); + + mutex_lock(&obj->dev->struct_mutex); + drm_vm_open_locked(vma); + mutex_unlock(&obj->dev->struct_mutex); } EXPORT_SYMBOL(drm_gem_vm_open); @@ -535,7 +513,10 @@ void drm_gem_vm_close(struct vm_area_struct *vma) { struct drm_gem_object *obj = vma->vm_private_data; - drm_gem_object_unreference_unlocked(obj); + mutex_lock(&obj->dev->struct_mutex); + drm_vm_close_locked(vma); + drm_gem_object_unreference(obj); + mutex_unlock(&obj->dev->struct_mutex); } EXPORT_SYMBOL(drm_gem_vm_close); diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 2ef2c7827243..974e970ce3f8 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -255,7 +255,7 @@ int drm_gem_one_name_info(int id, void *ptr, void *data) seq_printf(m, "%6d %8zd %7d %8d\n", obj->name, obj->size, - atomic_read(&obj->handlecount.refcount), + atomic_read(&obj->handle_count), atomic_read(&obj->refcount.refcount)); return 0; } diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index e2f70a516c34..9bf93bc9a32c 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -92,7 +92,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) } /* Contention */ + mutex_unlock(&drm_global_mutex); schedule(); + mutex_lock(&drm_global_mutex); if (signal_pending(current)) { ret = -EINTR; break; diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index da99edc50888..a6bfc302ed90 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -285,21 +285,21 @@ void drm_mm_put_block(struct drm_mm_node *cur) EXPORT_SYMBOL(drm_mm_put_block); -static int check_free_mm_node(struct drm_mm_node *entry, unsigned long size, - unsigned alignment) +static int check_free_hole(unsigned long start, unsigned long end, + unsigned long size, unsigned alignment) { unsigned wasted = 0; - if (entry->size < size) + if (end - start < size) return 0; if (alignment) { - register unsigned tmp = entry->start % alignment; + unsigned tmp = start % alignment; if (tmp) wasted = alignment - tmp; } - if (entry->size >= size + wasted) { + if (end >= start + size + wasted) { return 1; } @@ -320,7 +320,8 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, best_size = ~0UL; list_for_each_entry(entry, &mm->free_stack, free_stack) { - if (!check_free_mm_node(entry, size, alignment)) + if (!check_free_hole(entry->start, entry->start + entry->size, + size, alignment)) continue; if (!best_match) @@ -353,10 +354,12 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, best_size = ~0UL; list_for_each_entry(entry, &mm->free_stack, free_stack) { - if (entry->start > end || (entry->start+entry->size) < start) - continue; + unsigned long adj_start = entry->start < start ? + start : entry->start; + unsigned long adj_end = entry->start + entry->size > end ? + end : entry->start + entry->size; - if (!check_free_mm_node(entry, size, alignment)) + if (!check_free_hole(adj_start, adj_end, size, alignment)) continue; if (!best_match) @@ -449,7 +452,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) node->free_stack.prev = prev_free; node->free_stack.next = next_free; - if (check_free_mm_node(node, mm->scan_size, mm->scan_alignment)) { + if (check_free_hole(node->start, node->start + node->size, + mm->scan_size, mm->scan_alignment)) { mm->scan_hit_start = node->start; mm->scan_hit_size = node->size; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index f1f473ea97d3..949326d2a8e5 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -251,7 +251,10 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK; /* Fill in HSync values */ drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2; - drm_mode->hsync_start = drm_mode->hsync_end = CVT_RB_H_SYNC; + drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC; + /* Fill in VSync values */ + drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH; + drm_mode->vsync_end = drm_mode->vsync_start + vsync; } /* 15/13. Find pixel clock frequency (kHz for xf86) */ drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e20f78b542a7..f5bd9e590c80 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -164,6 +164,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, dev->hose = pdev->sysdata; #endif + mutex_lock(&drm_global_mutex); + if ((ret = drm_fill_in_dev(dev, ent, driver))) { printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); goto err_g2; @@ -199,6 +201,7 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent, driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, pci_name(pdev), dev->primary->index); + mutex_unlock(&drm_global_mutex); return 0; err_g4: @@ -210,6 +213,7 @@ err_g2: pci_disable_device(pdev); err_g1: kfree(dev); + mutex_unlock(&drm_global_mutex); return ret; } EXPORT_SYMBOL(drm_get_pci_dev); diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c index 460e9a3afa8d..92d1d0fb7b75 100644 --- a/drivers/gpu/drm/drm_platform.c +++ b/drivers/gpu/drm/drm_platform.c @@ -53,6 +53,8 @@ int drm_get_platform_dev(struct platform_device *platdev, dev->platformdev = platdev; dev->dev = &platdev->dev; + mutex_lock(&drm_global_mutex); + ret = drm_fill_in_dev(dev, NULL, driver); if (ret) { @@ -87,6 +89,8 @@ int drm_get_platform_dev(struct platform_device *platdev, list_add_tail(&dev->driver_item, &driver->device_list); + mutex_unlock(&drm_global_mutex); + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, dev->primary->index); @@ -100,6 +104,7 @@ err_g2: drm_put_minor(&dev->control); err_g1: kfree(dev); + mutex_unlock(&drm_global_mutex); return ret; } EXPORT_SYMBOL(drm_get_platform_dev); diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 86118a742231..85da4c40694c 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device, struct drm_connector *connector = to_drm_connector(device); enum drm_connector_status status; - status = connector->funcs->detect(connector); + status = connector->funcs->detect(connector, true); return snprintf(buf, PAGE_SIZE, "%s\n", drm_get_connector_status_name(status)); } diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 3778360eceea..5df450683aab 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -138,7 +138,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) break; } - if (!agpmem) + if (&agpmem->head == &dev->agp->memory) goto vm_fault_error; /* @@ -433,15 +433,7 @@ static void drm_vm_open(struct vm_area_struct *vma) mutex_unlock(&dev->struct_mutex); } -/** - * \c close method for all virtual memory types. - * - * \param vma virtual memory area. - * - * Search the \p vma private data entry in drm_device::vmalist, unlink it, and - * free it. - */ -static void drm_vm_close(struct vm_area_struct *vma) +void drm_vm_close_locked(struct vm_area_struct *vma) { struct drm_file *priv = vma->vm_file->private_data; struct drm_device *dev = priv->minor->dev; @@ -451,7 +443,6 @@ static void drm_vm_close(struct vm_area_struct *vma) vma->vm_start, vma->vm_end - vma->vm_start); atomic_dec(&dev->vma_count); - mutex_lock(&dev->struct_mutex); list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { if (pt->vma == vma) { list_del(&pt->head); @@ -459,6 +450,23 @@ static void drm_vm_close(struct vm_area_struct *vma) break; } } +} + +/** + * \c close method for all virtual memory types. + * + * \param vma virtual memory area. + * + * Search the \p vma private data entry in drm_device::vmalist, unlink it, and + * free it. + */ +static void drm_vm_close(struct vm_area_struct *vma) +{ + struct drm_file *priv = vma->vm_file->private_data; + struct drm_device *dev = priv->minor->dev; + + mutex_lock(&dev->struct_mutex); + drm_vm_close_locked(vma); mutex_unlock(&dev->struct_mutex); } diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 0e6c131313d9..fb07e73581e8 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -116,7 +116,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) static const struct file_operations i810_buffer_fops = { .open = drm_open, .release = drm_release, - .unlocked_ioctl = drm_ioctl, + .unlocked_ioctl = i810_ioctl, .mmap = i810_mmap_buffers, .fasync = drm_fasync, }; @@ -1255,21 +1255,21 @@ long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } struct drm_ioctl_desc i810_ioctls[] = { - DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED), }; int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c index 5168862c9227..cc92c7e6236f 100644 --- a/drivers/gpu/drm/i830/i830_dma.c +++ b/drivers/gpu/drm/i830/i830_dma.c @@ -118,7 +118,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) static const struct file_operations i830_buffer_fops = { .open = drm_open, .release = drm_release, - .unlocked_ioctl = drm_ioctl, + .unlocked_ioctl = i830_ioctl, .mmap = i830_mmap_buffers, .fasync = drm_fasync, }; @@ -1524,20 +1524,20 @@ long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } struct drm_ioctl_desc i830_ioctls[] = { - DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED), }; int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 92d5605a34d1..5e43d7076789 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -31,6 +31,7 @@ #include <linux/slab.h> #include "drmP.h" #include "drm.h" +#include "intel_drv.h" #include "i915_drm.h" #include "i915_drv.h" @@ -121,6 +122,54 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) return 0; } +static int i915_gem_pageflip_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + unsigned long flags; + struct intel_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + const char *pipe = crtc->pipe ? "B" : "A"; + const char *plane = crtc->plane ? "B" : "A"; + struct intel_unpin_work *work; + + spin_lock_irqsave(&dev->event_lock, flags); + work = crtc->unpin_work; + if (work == NULL) { + seq_printf(m, "No flip due on pipe %s (plane %s)\n", + pipe, plane); + } else { + if (!work->pending) { + seq_printf(m, "Flip queued on pipe %s (plane %s)\n", + pipe, plane); + } else { + seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n", + pipe, plane); + } + if (work->enable_stall_check) + seq_printf(m, "Stall check enabled, "); + else + seq_printf(m, "Stall check waiting for page flip ioctl, "); + seq_printf(m, "%d prepares\n", work->pending); + + if (work->old_fb_obj) { + struct drm_i915_gem_object *obj_priv = to_intel_bo(work->old_fb_obj); + if(obj_priv) + seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset ); + } + if (work->pending_flip_obj) { + struct drm_i915_gem_object *obj_priv = to_intel_bo(work->pending_flip_obj); + if(obj_priv) + seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset ); + } + } + spin_unlock_irqrestore(&dev->event_lock, flags); + } + + return 0; +} + static int i915_gem_request_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -777,6 +826,7 @@ static struct drm_info_list i915_debugfs_list[] = { {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST}, {"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST}, {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST}, + {"i915_gem_pageflip", i915_gem_pageflip_info, 0}, {"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 44af317731b6..2dd2c93ebfa3 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -620,8 +620,10 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, ret = copy_from_user(cliprects, batch->cliprects, batch->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_free; + } } mutex_lock(&dev->struct_mutex); @@ -662,8 +664,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return -ENOMEM; ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_batch_free; + } if (cmdbuf->num_cliprects) { cliprects = kcalloc(cmdbuf->num_cliprects, @@ -676,8 +680,10 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, ret = copy_from_user(cliprects, cmdbuf->cliprects, cmdbuf->num_cliprects * sizeof(struct drm_clip_rect)); - if (ret != 0) + if (ret != 0) { + ret = -EFAULT; goto fail_clip_free; + } } mutex_lock(&dev->struct_mutex); @@ -885,7 +891,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) int reg = IS_I965G(dev) ? MCHBAR_I965 : MCHBAR_I915; u32 temp_lo, temp_hi = 0; u64 mchbar_addr; - int ret = 0; + int ret; if (IS_I965G(dev)) pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi); @@ -895,22 +901,23 @@ intel_alloc_mchbar_resource(struct drm_device *dev) /* If ACPI doesn't have it, assume we need to allocate it ourselves */ #ifdef CONFIG_PNP if (mchbar_addr && - pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { - ret = 0; - goto out; - } + pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) + return 0; #endif /* Get some space for it */ - ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, &dev_priv->mch_res, + dev_priv->mch_res.name = "i915 MCHBAR"; + dev_priv->mch_res.flags = IORESOURCE_MEM; + ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus, + &dev_priv->mch_res, MCHBAR_SIZE, MCHBAR_SIZE, PCIBIOS_MIN_MEM, - 0, pcibios_align_resource, + 0, pcibios_align_resource, dev_priv->bridge_dev); if (ret) { DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret); dev_priv->mch_res.start = 0; - goto out; + return ret; } if (IS_I965G(dev)) @@ -919,8 +926,7 @@ intel_alloc_mchbar_resource(struct drm_device *dev) pci_write_config_dword(dev_priv->bridge_dev, reg, lower_32_bits(dev_priv->mch_res.start)); -out: - return ret; + return 0; } /* Setup MCHBAR if possible, return true if we should disable it again */ @@ -1781,9 +1787,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv) } } - div_u64(diff, diff1); + diff = div_u64(diff, diff1); ret = ((m * diff) + c); - div_u64(ret, 10); + ret = div_u64(ret, 10); dev_priv->last_count1 = total_count; dev_priv->last_time1 = now; @@ -1852,7 +1858,7 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv) /* More magic constants... */ diff = diff * 1181; - div_u64(diff, diffms * 10); + diff = div_u64(diff, diffms * 10); dev_priv->gfx_power = diff; } @@ -2082,6 +2088,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) goto free_priv; } + /* overlay on gen2 is broken and can't address above 1G */ + if (IS_GEN2(dev)) + dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); + dev_priv->regs = ioremap(base, size); if (!dev_priv->regs) { DRM_ERROR("failed to map registers\n"); @@ -2221,6 +2231,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->mchdev_lock = &mchdev_lock; spin_unlock(&mchdev_lock); + /* XXX Prevent module unload due to memory corruption bugs. */ + __module_get(THIS_MODULE); + return 0; out_workqueue_free: @@ -2367,46 +2380,46 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) } struct drm_ioctl_desc i915_ioctls[] = { - DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), - DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), - DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), - DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), - DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_FLUSH, i915_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_FLIP, i915_flip_bufs, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_ALLOC, i915_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_FREE, i915_mem_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 00befce8fbb7..6dbe14cc4f74 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -61,91 +61,86 @@ extern int intel_agp_enabled; .driver_data = (unsigned long) info } static const struct intel_device_info intel_i830_info = { - .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, + .gen = 2, .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_845g_info = { - .is_i8xx = 1, + .gen = 2, .is_i8xx = 1, }; static const struct intel_device_info intel_i85x_info = { - .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, + .gen = 2, .is_i8xx = 1, .is_i85x = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i865g_info = { - .is_i8xx = 1, + .gen = 2, .is_i8xx = 1, }; static const struct intel_device_info intel_i915g_info = { - .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, + .gen = 3, .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i915gm_info = { - .is_i9xx = 1, .is_mobile = 1, + .gen = 3, .is_i9xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i945g_info = { - .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, + .gen = 3, .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i945gm_info = { - .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, + .gen = 3, .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, }; static const struct intel_device_info intel_i965g_info = { - .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, + .gen = 4, .is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, + .has_hotplug = 1, }; static const struct intel_device_info intel_i965gm_info = { - .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, - .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, - .has_hotplug = 1, + .gen = 4, .is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1, + .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_g33_info = { - .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_hotplug = 1, + .gen = 3, .is_g33 = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_g45_info = { - .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_pipe_cxsr = 1, - .has_hotplug = 1, + .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .need_gfx_hws = 1, + .has_pipe_cxsr = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_gm45_info = { - .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, + .gen = 4, .is_i965g = 1, .is_g4x = 1, .is_i9xx = 1, .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, - .has_pipe_cxsr = 1, - .has_hotplug = 1, + .has_pipe_cxsr = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_pineview_info = { - .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, - .need_gfx_hws = 1, - .has_hotplug = 1, + .gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_ironlake_d_info = { - .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_pipe_cxsr = 1, - .has_hotplug = 1, + .gen = 5, .is_ironlake = 1, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_ironlake_m_info = { - .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, - .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, - .has_hotplug = 1, + .gen = 5, .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_sandybridge_d_info = { - .is_i965g = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_hotplug = 1, .is_gen6 = 1, + .gen = 6, .is_i965g = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { - .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, .need_gfx_hws = 1, - .has_hotplug = 1, .is_gen6 = 1, + .gen = 6, .is_i965g = 1, .is_mobile = 1, .is_i9xx = 1, + .need_gfx_hws = 1, .has_hotplug = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ @@ -175,13 +170,18 @@ static const struct pci_device_id pciidlist[] = { /* aka */ INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), /* G45_G */ INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), /* G41_G */ INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), /* B43_G */ + INTEL_VGA_DEVICE(0x2e92, &intel_g45_info), /* B43_G.1 */ INTEL_VGA_DEVICE(0xa001, &intel_pineview_info), INTEL_VGA_DEVICE(0xa011, &intel_pineview_info), INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info), INTEL_VGA_DEVICE(0x0046, &intel_ironlake_m_info), INTEL_VGA_DEVICE(0x0102, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0112, &intel_sandybridge_d_info), + INTEL_VGA_DEVICE(0x0122, &intel_sandybridge_d_info), INTEL_VGA_DEVICE(0x0106, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x0116, &intel_sandybridge_m_info), INTEL_VGA_DEVICE(0x0126, &intel_sandybridge_m_info), + INTEL_VGA_DEVICE(0x010A, &intel_sandybridge_d_info), {0, 0, 0} }; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 047cd7ce7e1b..af4a263cf257 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -191,6 +191,7 @@ struct drm_i915_display_funcs { }; struct intel_device_info { + u8 gen; u8 is_mobile : 1; u8 is_i8xx : 1; u8 is_i85x : 1; @@ -206,7 +207,6 @@ struct intel_device_info { u8 is_broadwater : 1; u8 is_crestline : 1; u8 is_ironlake : 1; - u8 is_gen6 : 1; u8 has_fbc : 1; u8 has_rc6 : 1; u8 has_pipe_cxsr : 1; @@ -1162,7 +1162,6 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove #define IS_845G(dev) ((dev)->pci_device == 0x2562) #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) #define IS_I865G(dev) ((dev)->pci_device == 0x2572) -#define IS_GEN2(dev) (INTEL_INFO(dev)->is_i8xx) #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) #define IS_I915GM(dev) ((dev)->pci_device == 0x2592) #define IS_I945G(dev) ((dev)->pci_device == 0x2772) @@ -1181,27 +1180,13 @@ extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_ove #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) #define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) #define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) -#define IS_GEN6(dev) (INTEL_INFO(dev)->is_gen6) #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) -#define IS_GEN3(dev) (IS_I915G(dev) || \ - IS_I915GM(dev) || \ - IS_I945G(dev) || \ - IS_I945GM(dev) || \ - IS_G33(dev) || \ - IS_PINEVIEW(dev)) -#define IS_GEN4(dev) ((dev)->pci_device == 0x2972 || \ - (dev)->pci_device == 0x2982 || \ - (dev)->pci_device == 0x2992 || \ - (dev)->pci_device == 0x29A2 || \ - (dev)->pci_device == 0x2A02 || \ - (dev)->pci_device == 0x2A12 || \ - (dev)->pci_device == 0x2E02 || \ - (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22 || \ - (dev)->pci_device == 0x2E32 || \ - (dev)->pci_device == 0x2A42 || \ - (dev)->pci_device == 0x2E42) +#define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) +#define IS_GEN3(dev) (INTEL_INFO(dev)->gen == 3) +#define IS_GEN4(dev) (INTEL_INFO(dev)->gen == 4) +#define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) +#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) #define HAS_BSD(dev) (IS_IRONLAKE(dev) || IS_G4X(dev)) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index df5a7135c261..90b1d6753b9d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -34,6 +34,7 @@ #include <linux/slab.h> #include <linux/swap.h> #include <linux/pci.h> +#include <linux/intel-gtt.h> static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); @@ -135,12 +136,13 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, return -ENOMEM; ret = drm_gem_handle_create(file_priv, obj, &handle); + /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(obj); - if (ret) + if (ret) { return ret; + } args->handle = handle; - return 0; } @@ -467,14 +469,17 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, return -ENOENT; obj_priv = to_intel_bo(obj); - /* Bounds check source. - * - * XXX: This could use review for overflow issues... - */ - if (args->offset > obj->size || args->size > obj->size || - args->offset + args->size > obj->size) { - drm_gem_object_unreference_unlocked(obj); - return -EINVAL; + /* Bounds check source. */ + if (args->offset > obj->size || args->size > obj->size - args->offset) { + ret = -EINVAL; + goto err; + } + + if (!access_ok(VERIFY_WRITE, + (char __user *)(uintptr_t)args->data_ptr, + args->size)) { + ret = -EFAULT; + goto err; } if (i915_gem_object_needs_bit17_swizzle(obj)) { @@ -486,8 +491,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, file_priv); } +err: drm_gem_object_unreference_unlocked(obj); - return ret; } @@ -576,8 +581,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; - if (!access_ok(VERIFY_READ, user_data, remain)) - return -EFAULT; mutex_lock(&dev->struct_mutex); @@ -930,14 +933,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, return -ENOENT; obj_priv = to_intel_bo(obj); - /* Bounds check destination. - * - * XXX: This could use review for overflow issues... - */ - if (args->offset > obj->size || args->size > obj->size || - args->offset + args->size > obj->size) { - drm_gem_object_unreference_unlocked(obj); - return -EINVAL; + /* Bounds check destination. */ + if (args->offset > obj->size || args->size > obj->size - args->offset) { + ret = -EINVAL; + goto err; + } + + if (!access_ok(VERIFY_READ, + (char __user *)(uintptr_t)args->data_ptr, + args->size)) { + ret = -EFAULT; + goto err; } /* We can only do the GTT pwrite on untiled buffers, as otherwise @@ -971,8 +977,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, DRM_INFO("pwrite failed %d\n", ret); #endif +err: drm_gem_object_unreference_unlocked(obj); - return ret; } @@ -2347,14 +2353,21 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) reg->obj = obj; - if (IS_GEN6(dev)) + switch (INTEL_INFO(dev)->gen) { + case 6: sandybridge_write_fence_reg(reg); - else if (IS_I965G(dev)) + break; + case 5: + case 4: i965_write_fence_reg(reg); - else if (IS_I9XX(dev)) + break; + case 3: i915_write_fence_reg(reg); - else + break; + case 2: i830_write_fence_reg(reg); + break; + } trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg, obj_priv->tiling_mode); @@ -2377,22 +2390,26 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[obj_priv->fence_reg]; + uint32_t fence_reg; - if (IS_GEN6(dev)) { + switch (INTEL_INFO(dev)->gen) { + case 6: I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (obj_priv->fence_reg * 8), 0); - } else if (IS_I965G(dev)) { + break; + case 5: + case 4: I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); - } else { - uint32_t fence_reg; - - if (obj_priv->fence_reg < 8) - fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; + break; + case 3: + if (obj_priv->fence_reg >= 8) + fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4; else - fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - - 8) * 4; + case 2: + fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; I915_WRITE(fence_reg, 0); + break; } reg->obj = NULL; @@ -3243,6 +3260,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, (int) reloc->offset, reloc->read_domains, reloc->write_domain); + drm_gem_object_unreference(target_obj); + i915_gem_object_unpin(obj); return -EINVAL; } if (reloc->write_domain & I915_GEM_DOMAIN_CPU || @@ -3585,6 +3604,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret != 0) { DRM_ERROR("copy %d cliprects failed: %d\n", args->num_cliprects, ret); + ret = -EFAULT; goto pre_mutex_err; } } diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 72cae3cccad8..5c428fa3e0b3 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -79,6 +79,7 @@ mark_free(struct drm_i915_gem_object *obj_priv, struct list_head *unwind) { list_add(&obj_priv->evict_list, unwind); + drm_gem_object_reference(&obj_priv->base); return drm_mm_scan_add_block(obj_priv->gtt_space); } @@ -92,7 +93,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen { drm_i915_private_t *dev_priv = dev->dev_private; struct list_head eviction_list, unwind_list; - struct drm_i915_gem_object *obj_priv, *tmp_obj_priv; + struct drm_i915_gem_object *obj_priv; struct list_head *render_iter, *bsd_iter; int ret = 0; @@ -165,6 +166,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen list_for_each_entry(obj_priv, &unwind_list, evict_list) { ret = drm_mm_scan_remove_block(obj_priv->gtt_space); BUG_ON(ret); + drm_gem_object_unreference(&obj_priv->base); } /* We expect the caller to unpin, evict all and try again, or give up. @@ -173,36 +175,34 @@ i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignmen return -ENOSPC; found: + /* drm_mm doesn't allow any other other operations while + * scanning, therefore store to be evicted objects on a + * temporary list. */ INIT_LIST_HEAD(&eviction_list); - list_for_each_entry_safe(obj_priv, tmp_obj_priv, - &unwind_list, evict_list) { + while (!list_empty(&unwind_list)) { + obj_priv = list_first_entry(&unwind_list, + struct drm_i915_gem_object, + evict_list); if (drm_mm_scan_remove_block(obj_priv->gtt_space)) { - /* drm_mm doesn't allow any other other operations while - * scanning, therefore store to be evicted objects on a - * temporary list. */ list_move(&obj_priv->evict_list, &eviction_list); + continue; } + list_del(&obj_priv->evict_list); + drm_gem_object_unreference(&obj_priv->base); } /* Unbinding will emit any required flushes */ - list_for_each_entry_safe(obj_priv, tmp_obj_priv, - &eviction_list, evict_list) { -#if WATCH_LRU - DRM_INFO("%s: evicting %p\n", __func__, obj); -#endif - ret = i915_gem_object_unbind(&obj_priv->base); - if (ret) - return ret; + while (!list_empty(&eviction_list)) { + obj_priv = list_first_entry(&eviction_list, + struct drm_i915_gem_object, + evict_list); + if (ret == 0) + ret = i915_gem_object_unbind(&obj_priv->base); + list_del(&obj_priv->evict_list); + drm_gem_object_unreference(&obj_priv->base); } - /* The just created free hole should be on the top of the free stack - * maintained by drm_mm, so this BUG_ON actually executes in O(1). - * Furthermore all accessed data has just recently been used, so it - * should be really fast, too. */ - BUG_ON(!drm_mm_search_free(&dev_priv->mm.gtt_space, min_size, - alignment, 0)); - - return 0; + return ret; } int diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 16861b800fee..744225ebb4b2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -887,6 +887,49 @@ static void i915_handle_error(struct drm_device *dev, bool wedged) queue_work(dev_priv->wq, &dev_priv->error_work); } +static void i915_pageflip_stall_check(struct drm_device *dev, int pipe) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_i915_gem_object *obj_priv; + struct intel_unpin_work *work; + unsigned long flags; + bool stall_detected; + + /* Ignore early vblank irqs */ + if (intel_crtc == NULL) + return; + + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; + + if (work == NULL || work->pending || !work->enable_stall_check) { + /* Either the pending flip IRQ arrived, or we're too early. Don't check */ + spin_unlock_irqrestore(&dev->event_lock, flags); + return; + } + + /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ + obj_priv = to_intel_bo(work->pending_flip_obj); + if(IS_I965G(dev)) { + int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; + stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; + } else { + int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR; + stall_detected = I915_READ(dspaddr) == (obj_priv->gtt_offset + + crtc->y * crtc->fb->pitch + + crtc->x * crtc->fb->bits_per_pixel/8); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); + + if (stall_detected) { + DRM_DEBUG_DRIVER("Pageflip stall detected\n"); + intel_prepare_page_flip(dev, intel_crtc->plane); + } +} + irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -1004,15 +1047,19 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (pipea_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 0); - if (!dev_priv->flip_pending_is_done) + if (!dev_priv->flip_pending_is_done) { + i915_pageflip_stall_check(dev, 0); intel_finish_page_flip(dev, 0); + } } if (pipeb_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 1); - if (!dev_priv->flip_pending_is_done) + if (!dev_priv->flip_pending_is_done) { + i915_pageflip_stall_check(dev, 1); intel_finish_page_flip(dev, 1); + } } if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) || @@ -1303,17 +1350,25 @@ void i915_hangcheck_elapsed(unsigned long data) i915_seqno_passed(i915_get_gem_seqno(dev, &dev_priv->render_ring), i915_get_tail_request(dev)->seqno)) { + bool missed_wakeup = false; + dev_priv->hangcheck_count = 0; /* Issue a wake-up to catch stuck h/w. */ - if (dev_priv->render_ring.waiting_gem_seqno | - dev_priv->bsd_ring.waiting_gem_seqno) { - DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n"); - if (dev_priv->render_ring.waiting_gem_seqno) - DRM_WAKEUP(&dev_priv->render_ring.irq_queue); - if (dev_priv->bsd_ring.waiting_gem_seqno) - DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); + if (dev_priv->render_ring.waiting_gem_seqno && + waitqueue_active(&dev_priv->render_ring.irq_queue)) { + DRM_WAKEUP(&dev_priv->render_ring.irq_queue); + missed_wakeup = true; } + + if (dev_priv->bsd_ring.waiting_gem_seqno && + waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { + DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); + missed_wakeup = true; + } + + if (missed_wakeup) + DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n"); return; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 67e3ec1a6af9..4f5e15577e89 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -319,6 +319,7 @@ #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) +# define MI_FLUSH_ENABLE (1 << 11) #define SCPD0 0x0209c /* 915+ only */ #define IER 0x020a0 @@ -2205,9 +2206,17 @@ #define WM1_LP_SR_EN (1<<31) #define WM1_LP_LATENCY_SHIFT 24 #define WM1_LP_LATENCY_MASK (0x7f<<24) +#define WM1_LP_FBC_LP1_MASK (0xf<<20) +#define WM1_LP_FBC_LP1_SHIFT 20 #define WM1_LP_SR_MASK (0x1ff<<8) #define WM1_LP_SR_SHIFT 8 #define WM1_LP_CURSOR_MASK (0x3f) +#define WM2_LP_ILK 0x4510c +#define WM2_LP_EN (1<<31) +#define WM3_LP_ILK 0x45110 +#define WM3_LP_EN (1<<31) +#define WM1S_LP_ILK 0x45120 +#define WM1S_LP_EN (1<<31) /* Memory latency timer register */ #define MLTR_ILK 0x11222 diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 2c6b98f2440e..31f08581e93a 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -789,16 +789,25 @@ int i915_save_state(struct drm_device *dev) dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); /* Fences */ - if (IS_I965G(dev)) { + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); + break; + case 5: + case 4: for (i = 0; i < 16; i++) dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); - } else { - for (i = 0; i < 8; i++) - dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); - + break; + case 3: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); + case 2: + for (i = 0; i < 8; i++) + dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); + break; + } return 0; @@ -815,15 +824,24 @@ int i915_restore_state(struct drm_device *dev) I915_WRITE(HWS_PGA, dev_priv->saveHWS); /* Fences */ - if (IS_I965G(dev)) { + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); + break; + case 5: + case 4: for (i = 0; i < 16; i++) I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]); - } else { - for (i = 0; i < 8; i++) - I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); + break; + case 3: + case 2: if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) for (i = 0; i < 8; i++) I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); + for (i = 0; i < 8; i++) + I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); + break; } i915_restore_display(dev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4b7735196cd5..197d4f32585a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -188,7 +188,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, 1000, 1)) - DRM_ERROR("timed out waiting for FORCE_TRIGGER"); + DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); if (turn_off_dac) { I915_WRITE(PCH_ADPA, temp); @@ -245,7 +245,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) if (wait_for((I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT) == 0, 1000, 1)) - DRM_ERROR("timed out waiting for FORCE_DETECT to go off"); + DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); } stat = I915_READ(PORT_HOTPLUG_STAT); @@ -400,7 +400,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder return status; } -static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_crt_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct drm_encoder *encoder = intel_attached_encoder(connector); @@ -419,6 +420,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto if (intel_crt_detect_ddc(encoder)) return connector_status_connected; + if (!force) + return connector->status; + /* for pre-945g platforms use load detect */ if (encoder->crtc && encoder->crtc->enabled) { status = intel_crt_load_detect(encoder->crtc, intel_encoder); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 23157e1de3be..979228594599 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -990,15 +990,31 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) struct drm_i915_private *dev_priv = dev->dev_private; int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT); + /* Clear existing vblank status. Note this will clear any other + * sticky status fields as well. + * + * This races with i915_driver_irq_handler() with the result + * that either function could miss a vblank event. Here it is not + * fatal, as we will either wait upon the next vblank interrupt or + * timeout. Generally speaking intel_wait_for_vblank() is only + * called during modeset at which time the GPU should be idle and + * should *not* be performing page flips and thus not waiting on + * vblanks... + * Currently, the result of us stealing a vblank from the irq + * handler is that a single frame will be skipped during swapbuffers. + */ + I915_WRITE(pipestat_reg, + I915_READ(pipestat_reg) | PIPE_VBLANK_INTERRUPT_STATUS); + /* Wait for vblank interrupt bit to set */ if (wait_for((I915_READ(pipestat_reg) & - PIPE_VBLANK_INTERRUPT_STATUS) == 0, + PIPE_VBLANK_INTERRUPT_STATUS), 50, 0)) DRM_DEBUG_KMS("vblank wait timed out\n"); } -/** - * intel_wait_for_vblank_off - wait for vblank after disabling a pipe +/* + * intel_wait_for_pipe_off - wait for pipe to turn off * @dev: drm device * @pipe: pipe to wait for * @@ -1006,25 +1022,39 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe) * spinning on the vblank interrupt status bit, since we won't actually * see an interrupt when the pipe is disabled. * - * So this function waits for the display line value to settle (it - * usually ends up stopping at the start of the next frame). + * On Gen4 and above: + * wait for the pipe register state bit to turn off + * + * Otherwise: + * wait for the display line value to settle (it usually + * ends up stopping at the start of the next frame). + * */ -void intel_wait_for_vblank_off(struct drm_device *dev, int pipe) +static void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); - unsigned long timeout = jiffies + msecs_to_jiffies(100); - u32 last_line; - - /* Wait for the display line to settle */ - do { - last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; - mdelay(5); - } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && - time_after(timeout, jiffies)); - - if (time_after(jiffies, timeout)) - DRM_DEBUG_KMS("vblank wait timed out\n"); + + if (INTEL_INFO(dev)->gen >= 4) { + int pipeconf_reg = (pipe == 0 ? PIPEACONF : PIPEBCONF); + + /* Wait for the Pipe State to go off */ + if (wait_for((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) == 0, + 100, 0)) + DRM_DEBUG_KMS("pipe_off wait timed out\n"); + } else { + u32 last_line; + int pipedsl_reg = (pipe == 0 ? PIPEADSL : PIPEBDSL); + unsigned long timeout = jiffies + msecs_to_jiffies(100); + + /* Wait for the display line to settle */ + do { + last_line = I915_READ(pipedsl_reg) & DSL_LINEMASK; + mdelay(5); + } while (((I915_READ(pipedsl_reg) & DSL_LINEMASK) != last_line) && + time_after(timeout, jiffies)); + if (time_after(jiffies, timeout)) + DRM_DEBUG_KMS("pipe_off wait timed out\n"); + } } /* Parameters have changed, update FBC info */ @@ -1486,7 +1516,7 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, dspcntr &= ~DISPPLANE_TILED; } - if (IS_IRONLAKE(dev)) + if (HAS_PCH_SPLIT(dev)) /* must disable */ dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; @@ -1495,20 +1525,19 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, Start = obj_priv->gtt_offset; Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); - DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y); + DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", + Start, Offset, x, y, fb->pitch); I915_WRITE(dspstride, fb->pitch); if (IS_I965G(dev)) { - I915_WRITE(dspbase, Offset); - I915_READ(dspbase); I915_WRITE(dspsurf, Start); - I915_READ(dspsurf); I915_WRITE(dsptileoff, (y << 16) | x); + I915_WRITE(dspbase, Offset); } else { I915_WRITE(dspbase, Start + Offset); - I915_READ(dspbase); } + POSTING_READ(dspbase); - if ((IS_I965G(dev) || plane == 0)) + if (IS_I965G(dev) || plane == 0) intel_update_fbc(crtc, &crtc->mode); intel_wait_for_vblank(dev, intel_crtc->pipe); @@ -1522,7 +1551,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; @@ -1530,13 +1558,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_gem_object *obj; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; - unsigned long Start, Offset; - int dspbase = (plane == 0 ? DSPAADDR : DSPBADDR); - int dspsurf = (plane == 0 ? DSPASURF : DSPBSURF); - int dspstride = (plane == 0) ? DSPASTRIDE : DSPBSTRIDE; - int dsptileoff = (plane == 0 ? DSPATILEOFF : DSPBTILEOFF); - int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR; - u32 dspcntr; int ret; /* no fb bound */ @@ -1572,71 +1593,18 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - dspcntr = I915_READ(dspcntr_reg); - /* Mask out pixel format bits in case we change it */ - dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; - switch (crtc->fb->bits_per_pixel) { - case 8: - dspcntr |= DISPPLANE_8BPP; - break; - case 16: - if (crtc->fb->depth == 15) - dspcntr |= DISPPLANE_15_16BPP; - else - dspcntr |= DISPPLANE_16BPP; - break; - case 24: - case 32: - if (crtc->fb->depth == 30) - dspcntr |= DISPPLANE_32BPP_30BIT_NO_ALPHA; - else - dspcntr |= DISPPLANE_32BPP_NO_ALPHA; - break; - default: - DRM_ERROR("Unknown color depth\n"); + ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); + if (ret) { i915_gem_object_unpin(obj); mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - if (IS_I965G(dev)) { - if (obj_priv->tiling_mode != I915_TILING_NONE) - dspcntr |= DISPPLANE_TILED; - else - dspcntr &= ~DISPPLANE_TILED; - } - - if (HAS_PCH_SPLIT(dev)) - /* must disable */ - dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; - - I915_WRITE(dspcntr_reg, dspcntr); - - Start = obj_priv->gtt_offset; - Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8); - - DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", - Start, Offset, x, y, crtc->fb->pitch); - I915_WRITE(dspstride, crtc->fb->pitch); - if (IS_I965G(dev)) { - I915_WRITE(dspsurf, Start); - I915_WRITE(dsptileoff, (y << 16) | x); - I915_WRITE(dspbase, Offset); - } else { - I915_WRITE(dspbase, Start + Offset); + return ret; } - POSTING_READ(dspbase); - - if ((IS_I965G(dev) || plane == 0)) - intel_update_fbc(crtc, &crtc->mode); - - intel_wait_for_vblank(dev, pipe); if (old_fb) { intel_fb = to_intel_framebuffer(old_fb); obj_priv = to_intel_bo(intel_fb->obj); i915_gem_object_unpin(intel_fb->obj); } - intel_increase_pllclock(crtc, true); mutex_unlock(&dev->struct_mutex); @@ -1911,9 +1879,6 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) int fdi_tx_reg = (pipe == 0) ? FDI_TXA_CTL : FDI_TXB_CTL; int fdi_rx_reg = (pipe == 0) ? FDI_RXA_CTL : FDI_RXB_CTL; int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF; - int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1; - int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ; - int pf_win_pos = (pipe == 0) ? PFA_WIN_POS : PFB_WIN_POS; int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; @@ -1982,15 +1947,19 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) } /* Enable panel fitting for LVDS */ - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) - || HAS_eDP || intel_pch_has_edp(crtc)) { - if (dev_priv->pch_pf_size) { - temp = I915_READ(pf_ctl_reg); - I915_WRITE(pf_ctl_reg, temp | PF_ENABLE | PF_FILTER_MED_3x3); - I915_WRITE(pf_win_pos, dev_priv->pch_pf_pos); - I915_WRITE(pf_win_size, dev_priv->pch_pf_size); - } else - I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); + if (dev_priv->pch_pf_size && + (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) + || HAS_eDP || intel_pch_has_edp(crtc))) { + /* Force use of hard-coded filter coefficients + * as some pre-programmed values are broken, + * e.g. x201. + */ + I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, + PF_ENABLE | PF_FILTER_MED_3x3); + I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS, + dev_priv->pch_pf_pos); + I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, + dev_priv->pch_pf_size); } /* Enable CPU pipe */ @@ -2115,7 +2084,7 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_READ(transconf_reg); - if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 10, 0)) + if (wait_for(I915_READ(transconf_reg) & TRANS_STATE_ENABLE, 100, 1)) DRM_ERROR("failed to enable transcoder\n"); } @@ -2155,14 +2124,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) udelay(100); /* Disable PF */ - temp = I915_READ(pf_ctl_reg); - if ((temp & PF_ENABLE) != 0) { - I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE); - I915_READ(pf_ctl_reg); - } - I915_WRITE(pf_win_size, 0); - POSTING_READ(pf_win_size); - + I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); + I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0); /* disable CPU FDI tx and PCH FDI rx */ temp = I915_READ(fdi_tx_reg); @@ -2379,13 +2342,13 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(dspbase_reg); } - /* Wait for vblank for the disable to take effect */ - intel_wait_for_vblank_off(dev, pipe); - /* Don't disable pipe A or pipe A PLLs if needed */ if (pipeconf_reg == PIPEACONF && - (dev_priv->quirks & QUIRK_PIPEA_FORCE)) + (dev_priv->quirks & QUIRK_PIPEA_FORCE)) { + /* Wait for vblank for the disable to take effect */ + intel_wait_for_vblank(dev, pipe); goto skip_pipe_off; + } /* Next, disable display pipes */ temp = I915_READ(pipeconf_reg); @@ -2394,8 +2357,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(pipeconf_reg); } - /* Wait for vblank for the disable to take effect. */ - intel_wait_for_vblank_off(dev, pipe); + /* Wait for the pipe to turn off */ + intel_wait_for_pipe_off(dev, pipe); temp = I915_READ(dpll_reg); if ((temp & DPLL_VCO_ENABLE) != 0) { @@ -2421,6 +2384,9 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode) int pipe = intel_crtc->pipe; bool enabled; + if (intel_crtc->dpms_mode == mode) + return; + intel_crtc->dpms_mode = mode; intel_crtc->cursor_on = mode == DRM_MODE_DPMS_ON; @@ -2511,11 +2477,19 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; + if (HAS_PCH_SPLIT(dev)) { /* FDI link clock is fixed at 2.7G */ if (mode->clock * 3 > IRONLAKE_FDI_FREQ * 4) return false; } + + /* XXX some encoders set the crtcinfo, others don't. + * Obviously we need some form of conflict resolution here... + */ + if (adjusted_mode->crtc_htotal == 0) + drm_mode_set_crtcinfo(adjusted_mode, 0); + return true; } @@ -2815,14 +2789,8 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz, /* Don't promote wm_size to unsigned... */ if (wm_size > (long)wm->max_wm) wm_size = wm->max_wm; - if (wm_size <= 0) { + if (wm_size <= 0) wm_size = wm->default_wm; - DRM_ERROR("Insufficient FIFO for plane, expect flickering:" - " entries required = %ld, available = %lu.\n", - entries_required + wm->guard_size, - wm->fifo_size); - } - return wm_size; } @@ -3436,8 +3404,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, reg_value = I915_READ(WM1_LP_ILK); reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK | WM1_LP_CURSOR_MASK); - reg_value |= WM1_LP_SR_EN | - (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | + reg_value |= (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm; I915_WRITE(WM1_LP_ILK, reg_value); @@ -3554,10 +3521,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, u32 dpll = 0, fp = 0, fp2 = 0, dspcntr, pipeconf; bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; - bool is_edp = false; + struct intel_encoder *has_edp_encoder = NULL; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_encoder *encoder; - struct intel_encoder *intel_encoder = NULL; const intel_limit_t *limit; int ret; struct fdi_m_n m_n = {0}; @@ -3578,12 +3544,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, drm_vblank_pre_modeset(dev, pipe); list_for_each_entry(encoder, &mode_config->encoder_list, head) { + struct intel_encoder *intel_encoder; - if (!encoder || encoder->crtc != crtc) + if (encoder->crtc != crtc) continue; intel_encoder = enc_to_intel_encoder(encoder); - switch (intel_encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; @@ -3607,7 +3573,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, is_dp = true; break; case INTEL_OUTPUT_EDP: - is_edp = true; + has_edp_encoder = intel_encoder; break; } @@ -3685,10 +3651,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, int lane = 0, link_bw, bpp; /* eDP doesn't require FDI link, so just set DP M/N according to current link config */ - if (is_edp) { + if (has_edp_encoder) { target_clock = mode->clock; - intel_edp_link_config(intel_encoder, - &lane, &link_bw); + intel_edp_link_config(has_edp_encoder, + &lane, &link_bw); } else { /* DP over FDI requires target mode clock instead of link clock */ @@ -3709,7 +3675,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, temp |= PIPE_8BPC; else temp |= PIPE_6BPC; - } else if (is_edp || (is_dp && intel_pch_has_edp(crtc))) { + } else if (has_edp_encoder || (is_dp && intel_pch_has_edp(crtc))) { switch (dev_priv->edp_bpp/3) { case 8: temp |= PIPE_8BPC; @@ -3782,7 +3748,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, udelay(200); - if (is_edp) { + if (has_edp_encoder) { if (dev_priv->lvds_use_ssc) { temp |= DREF_SSC1_ENABLE; I915_WRITE(PCH_DREF_CONTROL, temp); @@ -3931,7 +3897,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, dpll_reg = pch_dpll_reg; } - if (!is_edp) { + if (!has_edp_encoder) { I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); I915_READ(dpll_reg); @@ -4026,7 +3992,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, } } - if (!is_edp) { + if (!has_edp_encoder) { I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll); I915_READ(dpll_reg); @@ -4105,7 +4071,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(link_m1_reg, m_n.link_m); I915_WRITE(link_n1_reg, m_n.link_n); - if (is_edp) { + if (has_edp_encoder) { ironlake_set_pll_edp(crtc, adjusted_mode->clock); } else { /* enable FDI RX PLL too */ @@ -4911,15 +4877,6 @@ static void intel_crtc_destroy(struct drm_crtc *crtc) kfree(intel_crtc); } -struct intel_unpin_work { - struct work_struct work; - struct drm_device *dev; - struct drm_gem_object *old_fb_obj; - struct drm_gem_object *pending_flip_obj; - struct drm_pending_vblank_event *event; - int pending; -}; - static void intel_unpin_work_fn(struct work_struct *__work) { struct intel_unpin_work *work = @@ -5007,7 +4964,8 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane) spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) { - intel_crtc->unpin_work->pending = 1; + if ((++intel_crtc->unpin_work->pending) > 1) + DRM_ERROR("Prepared flip multiple times\n"); } else { DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); } @@ -5026,9 +4984,9 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; unsigned long flags, offset; - int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC; - int ret, pipesrc; - u32 flip_mask; + int pipe = intel_crtc->pipe; + u32 pf, pipesrc; + int ret; work = kzalloc(sizeof *work, GFP_KERNEL); if (work == NULL) @@ -5077,42 +5035,73 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, atomic_inc(&obj_priv->pending_flip); work->pending_flip_obj = obj; - if (intel_crtc->plane) - flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; - else - flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - if (IS_GEN3(dev) || IS_GEN2(dev)) { + u32 flip_mask; + + if (intel_crtc->plane) + flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; + else + flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; + BEGIN_LP_RING(2); OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); OUT_RING(0); ADVANCE_LP_RING(); } + work->enable_stall_check = true; + /* Offset into the new buffer for cases of shared fbs between CRTCs */ - offset = obj_priv->gtt_offset; - offset += (crtc->y * fb->pitch) + (crtc->x * (fb->bits_per_pixel) / 8); + offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; BEGIN_LP_RING(4); - if (IS_I965G(dev)) { + switch(INTEL_INFO(dev)->gen) { + case 2: OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(offset | obj_priv->tiling_mode); - pipesrc = I915_READ(pipesrc_reg); - OUT_RING(pipesrc & 0x0fff0fff); - } else if (IS_GEN3(dev)) { + OUT_RING(obj_priv->gtt_offset + offset); + OUT_RING(MI_NOOP); + break; + + case 3: OUT_RING(MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(offset); + OUT_RING(obj_priv->gtt_offset + offset); OUT_RING(MI_NOOP); - } else { + break; + + case 4: + case 5: + /* i965+ uses the linear or tiled offsets from the + * Display Registers (which do not change across a page-flip) + * so we need only reprogram the base address. + */ OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(offset); - OUT_RING(MI_NOOP); + OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); + + /* XXX Enabling the panel-fitter across page-flip is so far + * untested on non-native modes, so ignore it for now. + * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; + */ + pf = 0; + pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + break; + + case 6: + OUT_RING(MI_DISPLAY_FLIP | + MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); + OUT_RING(fb->pitch | obj_priv->tiling_mode); + OUT_RING(obj_priv->gtt_offset); + + pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; + pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; + OUT_RING(pf | pipesrc); + break; } ADVANCE_LP_RING(); @@ -5193,7 +5182,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base; intel_crtc->cursor_addr = 0; - intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF; + intel_crtc->dpms_mode = -1; drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); intel_crtc->busy = false; @@ -5701,6 +5690,9 @@ void intel_init_clock_gating(struct drm_device *dev) I915_WRITE(DISP_ARB_CTL, (I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS)); + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); } /* * Based on the document from hardware guys the following bits @@ -5722,8 +5714,7 @@ void intel_init_clock_gating(struct drm_device *dev) ILK_DPFC_DIS2 | ILK_CLK_FBC); } - if (IS_GEN6(dev)) - return; + return; } else if (IS_G4X(dev)) { uint32_t dspclk_gate; I915_WRITE(RENCLK_GATE_D1, 0); @@ -5784,11 +5775,9 @@ void intel_init_clock_gating(struct drm_device *dev) OUT_RING(MI_FLUSH); ADVANCE_LP_RING(); } - } else { + } else DRM_DEBUG_KMS("Failed to allocate render context." - "Disable RC6\n"); - return; - } + "Disable RC6\n"); } if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 9caccd03dccb..9ab8708ac6ba 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -239,7 +239,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, uint32_t ch_data = ch_ctl + 4; int i; int recv_bytes; - uint32_t ctl; uint32_t status; uint32_t aux_clock_divider; int try, precharge; @@ -263,41 +262,43 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else precharge = 5; + if (I915_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { + DRM_ERROR("dp_aux_ch not started status 0x%08x\n", + I915_READ(ch_ctl)); + return -EBUSY; + } + /* Must try at least 3 times according to DP spec */ for (try = 0; try < 5; try++) { /* Load the send data into the aux channel data registers */ - for (i = 0; i < send_bytes; i += 4) { - uint32_t d = pack_aux(send + i, send_bytes - i); - - I915_WRITE(ch_data + i, d); - } - - ctl = (DP_AUX_CH_CTL_SEND_BUSY | - DP_AUX_CH_CTL_TIME_OUT_400us | - (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | - (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | - (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR); + for (i = 0; i < send_bytes; i += 4) + I915_WRITE(ch_data + i, + pack_aux(send + i, send_bytes - i)); /* Send the command and wait for it to complete */ - I915_WRITE(ch_ctl, ctl); - (void) I915_READ(ch_ctl); + I915_WRITE(ch_ctl, + DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); for (;;) { - udelay(100); status = I915_READ(ch_ctl); if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) break; + udelay(100); } /* Clear done status and any errors */ - I915_WRITE(ch_ctl, (status | - DP_AUX_CH_CTL_DONE | - DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_RECEIVE_ERROR)); - (void) I915_READ(ch_ctl); - if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) + I915_WRITE(ch_ctl, + status | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + if (status & DP_AUX_CH_CTL_DONE) break; } @@ -324,15 +325,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, /* Unload any bytes sent back from the other side */ recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); - if (recv_bytes > recv_size) recv_bytes = recv_size; - for (i = 0; i < recv_bytes; i += 4) { - uint32_t d = I915_READ(ch_data + i); - - unpack_aux(d, recv + i, recv_bytes - i); - } + for (i = 0; i < recv_bytes; i += 4) + unpack_aux(I915_READ(ch_data + i), + recv + i, recv_bytes - i); return recv_bytes; } @@ -1140,18 +1138,14 @@ static bool intel_dp_set_link_train(struct intel_dp *intel_dp, uint32_t dp_reg_value, uint8_t dp_train_pat, - uint8_t train_set[4], - bool first) + uint8_t train_set[4]) { struct drm_device *dev = intel_dp->base.enc.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); int ret; I915_WRITE(intel_dp->output_reg, dp_reg_value); POSTING_READ(intel_dp->output_reg); - if (first) - intel_wait_for_vblank(dev, intel_crtc->pipe); intel_dp_aux_native_write_1(intel_dp, DP_TRAINING_PATTERN_SET, @@ -1176,10 +1170,15 @@ intel_dp_link_train(struct intel_dp *intel_dp) uint8_t voltage; bool clock_recovery = false; bool channel_eq = false; - bool first = true; int tries; u32 reg; uint32_t DP = intel_dp->DP; + struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.enc.crtc); + + /* Enable output, wait for it to become active */ + I915_WRITE(intel_dp->output_reg, intel_dp->DP); + POSTING_READ(intel_dp->output_reg); + intel_wait_for_vblank(dev, intel_crtc->pipe); /* Write the link configuration data */ intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, @@ -1212,9 +1211,8 @@ intel_dp_link_train(struct intel_dp *intel_dp) reg = DP | DP_LINK_TRAIN_PAT_1; if (!intel_dp_set_link_train(intel_dp, reg, - DP_TRAINING_PATTERN_1, train_set, first)) + DP_TRAINING_PATTERN_1, train_set)) break; - first = false; /* Set training pattern 1 */ udelay(100); @@ -1268,8 +1266,7 @@ intel_dp_link_train(struct intel_dp *intel_dp) /* channel eq pattern */ if (!intel_dp_set_link_train(intel_dp, reg, - DP_TRAINING_PATTERN_2, train_set, - false)) + DP_TRAINING_PATTERN_2, train_set)) break; udelay(400); @@ -1388,7 +1385,7 @@ ironlake_dp_detect(struct drm_connector *connector) * \return false if DP port is disconnected. */ static enum drm_connector_status -intel_dp_detect(struct drm_connector *connector) +intel_dp_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0e92aa07b382..8828b3ac6414 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -176,6 +176,16 @@ struct intel_crtc { #define enc_to_intel_encoder(x) container_of(x, struct intel_encoder, enc) #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) +struct intel_unpin_work { + struct work_struct work; + struct drm_device *dev; + struct drm_gem_object *old_fb_obj; + struct drm_gem_object *pending_flip_obj; + struct drm_pending_vblank_event *event; + int pending; + bool enable_stall_check; +}; + struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, const char *name); void intel_i2c_destroy(struct i2c_adapter *adapter); @@ -219,7 +229,6 @@ extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc); int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void intel_wait_for_vblank_off(struct drm_device *dev, int pipe); extern void intel_wait_for_vblank(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe); extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_encoder *intel_encoder, diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index a399f4b2c1c5..7c9ec1472d46 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -221,7 +221,8 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, * * Unimplemented. */ -static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_dvo_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 7bdc96256bf5..b61966c126d3 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -237,8 +237,10 @@ int intel_fbdev_destroy(struct drm_device *dev, drm_fb_helper_fini(&ifbdev->helper); drm_framebuffer_cleanup(&ifb->base); - if (ifb->obj) + if (ifb->obj) { drm_gem_object_unreference(ifb->obj); + ifb->obj = NULL; + } return 0; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index ccd4c97e6524..926934a482ec 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -139,7 +139,7 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, } static enum drm_connector_status -intel_hdmi_detect(struct drm_connector *connector) +intel_hdmi_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder = intel_attached_encoder(connector); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b819c1081147..6ec39a86ed06 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -445,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, * connected and closed means disconnected. We also send hotplug events as * needed, using lid status notification from the input layer. */ -static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_lvds_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; enum drm_connector_status status = connector_status_connected; @@ -540,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, * the LID nofication event. */ if (connector) - connector->status = connector->funcs->detect(connector); + connector->status = connector->funcs->detect(connector, + false); + /* Don't force modeset on machines where it causes a GPU lockup */ if (dmi_check_system(intel_no_modeset_on_lid)) return NOTIFY_OK; @@ -875,8 +878,6 @@ void intel_lvds_init(struct drm_device *dev) intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); intel_encoder->crtc_mask = (1 << 1); - if (IS_I965G(dev)) - intel_encoder->crtc_mask |= (1 << 0); drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 4f00390d7c61..1d306a458be6 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -25,6 +25,8 @@ * * Derived from Xorg ddx, xf86-video-intel, src/i830_video.c */ + +#include <linux/seq_file.h> #include "drmP.h" #include "drm.h" #include "i915_drm.h" diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 51e9c9e718c4..cb3508f78bc3 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -220,9 +220,13 @@ static int init_render_ring(struct drm_device *dev, { drm_i915_private_t *dev_priv = dev->dev_private; int ret = init_ring_common(dev, ring); + int mode; + if (IS_I9XX(dev) && !IS_GEN3(dev)) { - I915_WRITE(MI_MODE, - (VS_TIMER_DISPATCH) << 16 | VS_TIMER_DISPATCH); + mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; + if (IS_GEN6(dev)) + mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; + I915_WRITE(MI_MODE, mode); } return ret; } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 093e914e8a41..ee73e428a84a 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1061,8 +1061,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) return false; - if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode)) - return false; + (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, + mode, + adjusted_mode); } else if (intel_sdvo->is_lvds) { drm_mode_set_crtcinfo(intel_sdvo->sdvo_lvds_fixed_mode, 0); @@ -1070,8 +1071,9 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, intel_sdvo->sdvo_lvds_fixed_mode)) return false; - if (!intel_sdvo_set_input_timings_for_mode(intel_sdvo, mode, adjusted_mode)) - return false; + (void) intel_sdvo_set_input_timings_for_mode(intel_sdvo, + mode, + adjusted_mode); } /* Make the CRTC code factor in the SDVO pixel multiplier. The @@ -1108,10 +1110,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, in_out.in0 = intel_sdvo->attached_output; in_out.in1 = 0; - if (!intel_sdvo_set_value(intel_sdvo, - SDVO_CMD_SET_IN_OUT_MAP, - &in_out, sizeof(in_out))) - return; + intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_IN_OUT_MAP, + &in_out, sizeof(in_out)); if (intel_sdvo->is_hdmi) { if (!intel_sdvo_set_avi_infoframe(intel_sdvo, mode)) @@ -1122,11 +1123,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, /* We have tried to get input timing in mode_fixup, and filled into adjusted_mode */ - if (intel_sdvo->is_tv || intel_sdvo->is_lvds) { - intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); + if (intel_sdvo->is_tv || intel_sdvo->is_lvds) input_dtd.part2.sdvo_flags = intel_sdvo->sdvo_flags; - } else - intel_sdvo_get_dtd_from_mode(&input_dtd, mode); /* If it's a TV, we already set the output timing in mode_fixup. * Otherwise, the output timing is equal to the input timing. @@ -1137,8 +1136,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, intel_sdvo->attached_output)) return; - if (!intel_sdvo_set_output_timing(intel_sdvo, &input_dtd)) - return; + (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd); } /* Set the input timing to the screen. Assume always input 0. */ @@ -1165,8 +1163,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, intel_sdvo_set_input_timing(encoder, &input_dtd); } #else - if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) - return; + (void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd); #endif sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); @@ -1420,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev) if (!analog_connector) return false; - if (analog_connector->funcs->detect(analog_connector) == + if (analog_connector->funcs->detect(analog_connector, false) == connector_status_disconnected) return false; @@ -1489,7 +1486,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) return status; } -static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) +static enum drm_connector_status +intel_sdvo_detect(struct drm_connector *connector, bool force) { uint16_t response; struct drm_encoder *encoder = intel_attached_encoder(connector); @@ -1932,6 +1930,41 @@ static const struct drm_encoder_funcs intel_sdvo_enc_funcs = { .destroy = intel_sdvo_enc_destroy, }; +static void +intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) +{ + uint16_t mask = 0; + unsigned int num_bits; + + /* Make a mask of outputs less than or equal to our own priority in the + * list. + */ + switch (sdvo->controlled_output) { + case SDVO_OUTPUT_LVDS1: + mask |= SDVO_OUTPUT_LVDS1; + case SDVO_OUTPUT_LVDS0: + mask |= SDVO_OUTPUT_LVDS0; + case SDVO_OUTPUT_TMDS1: + mask |= SDVO_OUTPUT_TMDS1; + case SDVO_OUTPUT_TMDS0: + mask |= SDVO_OUTPUT_TMDS0; + case SDVO_OUTPUT_RGB1: + mask |= SDVO_OUTPUT_RGB1; + case SDVO_OUTPUT_RGB0: + mask |= SDVO_OUTPUT_RGB0; + break; + } + + /* Count bits to find what number we are in the priority list. */ + mask &= sdvo->caps.output_flags; + num_bits = hweight16(mask); + /* If more than 3 outputs, default to DDC bus 3 for now. */ + if (num_bits > 3) + num_bits = 3; + + /* Corresponds to SDVO_CONTROL_BUS_DDCx */ + sdvo->ddc_bus = 1 << num_bits; +} /** * Choose the appropriate DDC bus for control bus switch command for this @@ -1951,7 +1984,10 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv, else mapping = &(dev_priv->sdvo_mappings[1]); - sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); + if (mapping->initialized) + sdvo->ddc_bus = 1 << ((mapping->ddc_pin & 0xf0) >> 4); + else + intel_sdvo_guess_ddc_bus(sdvo); } static bool @@ -2134,8 +2170,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) return true; err: - intel_sdvo_destroy_enhance_property(connector); - kfree(intel_sdvo_connector); + intel_sdvo_destroy(connector); return false; } @@ -2207,8 +2242,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) return true; err: - intel_sdvo_destroy_enhance_property(connector); - kfree(intel_sdvo_connector); + intel_sdvo_destroy(connector); return false; } @@ -2486,11 +2520,10 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo, uint16_t response; } enhancements; - if (!intel_sdvo_get_value(intel_sdvo, - SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, - &enhancements, sizeof(enhancements))) - return false; - + enhancements.response = 0; + intel_sdvo_get_value(intel_sdvo, + SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS, + &enhancements, sizeof(enhancements)); if (enhancements.response == 0) { DRM_DEBUG_KMS("No enhancement is supported\n"); return true; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d2029efee982..4a117e318a73 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1231,7 +1231,6 @@ intel_tv_detect_type (struct intel_tv *intel_tv) struct drm_encoder *encoder = &intel_tv->base.enc; struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); unsigned long irqflags; u32 tv_ctl, save_tv_ctl; u32 tv_dac, save_tv_dac; @@ -1268,11 +1267,15 @@ intel_tv_detect_type (struct intel_tv *intel_tv) DAC_C_0_7_V); I915_WRITE(TV_CTL, tv_ctl); I915_WRITE(TV_DAC, tv_dac); - intel_wait_for_vblank(dev, intel_crtc->pipe); + POSTING_READ(TV_DAC); + msleep(20); + tv_dac = I915_READ(TV_DAC); I915_WRITE(TV_DAC, save_tv_dac); I915_WRITE(TV_CTL, save_tv_ctl); - intel_wait_for_vblank(dev, intel_crtc->pipe); + POSTING_READ(TV_CTL); + msleep(20); + /* * A B C * 0 1 1 Composite @@ -1338,7 +1341,7 @@ static void intel_tv_find_better_format(struct drm_connector *connector) * we have a pipe programmed in order to probe the TV. */ static enum drm_connector_status -intel_tv_detect(struct drm_connector *connector) +intel_tv_detect(struct drm_connector *connector, bool force) { struct drm_display_mode mode; struct drm_encoder *encoder = intel_attached_encoder(connector); @@ -1350,7 +1353,7 @@ intel_tv_detect(struct drm_connector *connector) if (encoder->crtc && encoder->crtc->enabled) { type = intel_tv_detect_type(intel_tv); - } else { + } else if (force) { struct drm_crtc *crtc; int dpms_mode; @@ -1361,10 +1364,9 @@ intel_tv_detect(struct drm_connector *connector) intel_release_load_detect_pipe(&intel_tv->base, connector, dpms_mode); } else - type = -1; - } - - intel_tv->type = type; + return connector_status_unknown; + } else + return connector->status; if (type < 0) return connector_status_disconnected; diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c index fff82045c427..9ce2827f8c00 100644 --- a/drivers/gpu/drm/mga/mga_state.c +++ b/drivers/gpu/drm/mga/mga_state.c @@ -1085,19 +1085,19 @@ file_priv) } struct drm_ioctl_desc mga_ioctls[] = { - DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), - DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), + DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), }; int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 0b69a9628c95..974b0f8ae048 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -2166,7 +2166,7 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, uint32_t val = 0; if (off < pci_resource_len(dev->pdev, 1)) { - uint32_t __iomem *p = + uint8_t __iomem *p = io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); val = ioread32(p + (off & ~PAGE_MASK)); @@ -2182,7 +2182,7 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, uint32_t off, uint32_t val) { if (off < pci_resource_len(dev->pdev, 1)) { - uint32_t __iomem *p = + uint8_t __iomem *p = io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); iowrite32(val, p + (off & ~PAGE_MASK)); @@ -3869,27 +3869,10 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr } #ifdef __powerpc__ /* Powerbook specific quirks */ - if ((dev->pci_device & 0xffff) == 0x0179 || - (dev->pci_device & 0xffff) == 0x0189 || - (dev->pci_device & 0xffff) == 0x0329) { - if (script == LVDS_RESET) { - nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); - - } else if (script == LVDS_PANEL_ON) { - bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, - bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) - | (1 << 31)); - bios_wr32(bios, NV_PCRTC_GPIO_EXT, - bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); - - } else if (script == LVDS_PANEL_OFF) { - bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, - bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) - & ~(1 << 31)); - bios_wr32(bios, NV_PCRTC_GPIO_EXT, - bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); - } - } + if (script == LVDS_RESET && + (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || + dev->pci_device == 0x0329)) + nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); #endif return 0; @@ -4381,11 +4364,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b * * For the moment, a quirk will do :) */ - if ((dev->pdev->device == 0x01d7) && - (dev->pdev->subsystem_vendor == 0x1028) && - (dev->pdev->subsystem_device == 0x01c2)) { + if (nv_match_device(dev, 0x01d7, 0x1028, 0x01c2)) bios->fp.duallink_transition_clk = 80000; - } /* set dual_link flag for EDID case */ if (pxclk && (chip_version < 0x25 || chip_version > 0x28)) @@ -4587,7 +4567,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, return 1; } - NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent); } else if (pxclk == -1) { @@ -4597,7 +4577,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, return 1; } - NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent); } else if (pxclk == -2) { @@ -4610,7 +4590,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, return 1; } - NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); + NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); nouveau_bios_run_init_table(dev, script, dcbent); } else if (pxclk > 0) { @@ -4622,7 +4602,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, return 1; } - NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); + NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); nouveau_bios_run_init_table(dev, script, dcbent); } else if (pxclk < 0) { @@ -4634,7 +4614,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, return 1; } - NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); + NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); nouveau_bios_run_init_table(dev, script, dcbent); } @@ -5357,19 +5337,17 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, } tmdstableptr = ROM16(bios->data[bitentry->offset]); - - if (tmdstableptr == 0x0) { + if (!tmdstableptr) { NV_ERROR(dev, "Pointer to TMDS table invalid\n"); return -EINVAL; } + NV_INFO(dev, "TMDS table version %d.%d\n", + bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); + /* nv50+ has v2.0, but we don't parse it atm */ - if (bios->data[tmdstableptr] != 0x11) { - NV_WARN(dev, - "TMDS table revision %d.%d not currently supported\n", - bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); + if (bios->data[tmdstableptr] != 0x11) return -ENOSYS; - } /* * These two scripts are odd: they don't seem to get run even when @@ -5809,6 +5787,20 @@ parse_dcb_gpio_table(struct nvbios *bios) gpio->line = tvdac_gpio[1] >> 4; gpio->invert = tvdac_gpio[0] & 2; } + } else { + /* + * No systematic way to store GPIO info on pre-v2.2 + * DCBs, try to match the PCI device IDs. + */ + + /* Apple iMac G4 NV18 */ + if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { + struct dcb_gpio_entry *gpio = new_gpio_entry(bios); + + gpio->tag = DCB_GPIO_TVDAC0; + gpio->line = 4; + } + } if (!gpio_table_ptr) @@ -5884,9 +5876,7 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) struct drm_device *dev = bios->dev; /* Gigabyte NX85T */ - if ((dev->pdev->device == 0x0421) && - (dev->pdev->subsystem_vendor == 0x1458) && - (dev->pdev->subsystem_device == 0x344c)) { + if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) { if (cte->type == DCB_CONNECTOR_HDMI_1) cte->type = DCB_CONNECTOR_DVI_I; } @@ -6139,7 +6129,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; break; - case 0xe: + case OUTPUT_EOL: /* weird g80 mobile type that "nv" treats as a terminator */ dcb->entries--; return false; @@ -6176,22 +6166,14 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, entry->type = OUTPUT_TV; break; case 2: - case 3: - entry->type = OUTPUT_LVDS; - break; case 4: - switch ((conn & 0x000000f0) >> 4) { - case 0: - entry->type = OUTPUT_TMDS; - break; - case 1: + if (conn & 0x10) entry->type = OUTPUT_LVDS; - break; - default: - NV_ERROR(dev, "Unknown DCB subtype 4/%d\n", - (conn & 0x000000f0) >> 4); - return false; - } + else + entry->type = OUTPUT_TMDS; + break; + case 3: + entry->type = OUTPUT_LVDS; break; default: NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); @@ -6307,9 +6289,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) * nasty problems until this is sorted (assuming it's not a * VBIOS bug). */ - if ((dev->pdev->device == 0x040d) && - (dev->pdev->subsystem_vendor == 0x1028) && - (dev->pdev->subsystem_device == 0x019b)) { + if (nv_match_device(dev, 0x040d, 0x1028, 0x019b)) { if (*conn == 0x02026312 && *conf == 0x00000020) return false; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index fd14dfd3d780..c1de2f3fcb0e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -95,6 +95,7 @@ enum dcb_type { OUTPUT_TMDS = 2, OUTPUT_LVDS = 3, OUTPUT_DP = 6, + OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */ OUTPUT_ANY = -1 }; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 84f85183d041..f6f44779d82f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -36,6 +36,21 @@ #include <linux/log2.h> #include <linux/slab.h> +int +nouveau_bo_sync_gpu(struct nouveau_bo *nvbo, struct nouveau_channel *chan) +{ + struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; + int ret; + + if (!prev_fence || nouveau_fence_channel(prev_fence) == chan) + return 0; + + spin_lock(&nvbo->bo.lock); + ret = ttm_bo_wait(&nvbo->bo, false, false, false); + spin_unlock(&nvbo->bo.lock); + return ret; +} + static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 90fdcda332be..0480f064f2c1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -426,18 +426,18 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, ***********************************/ struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH), - DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH), }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index b1b22baf1428..fc737037f751 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -104,7 +104,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, int i; for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - struct nouveau_i2c_chan *i2c; + struct nouveau_i2c_chan *i2c = NULL; struct nouveau_encoder *nv_encoder; struct drm_mode_object *obj; int id; @@ -117,7 +117,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, if (!obj) continue; nv_encoder = nouveau_encoder(obj_to_encoder(obj)); - i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); + + if (nv_encoder->dcb->i2c_index < 0xf) + i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) { *pnv_encoder = nv_encoder; @@ -166,7 +168,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, } static enum drm_connector_status -nouveau_connector_detect(struct drm_connector *connector) +nouveau_connector_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct nouveau_connector *nv_connector = nouveau_connector(connector); @@ -244,7 +246,7 @@ detect_analog: } static enum drm_connector_status -nouveau_connector_detect_lvds(struct drm_connector *connector) +nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -265,7 +267,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector) /* Try retrieving EDID via DDC */ if (!dev_priv->vbios.fp_no_ddc) { - status = nouveau_connector_detect(connector); + status = nouveau_connector_detect(connector, force); if (status == connector_status_connected) goto out; } @@ -556,8 +558,10 @@ nouveau_connector_get_modes(struct drm_connector *connector) if (nv_encoder->dcb->type == OUTPUT_LVDS && (nv_encoder->dcb->lvdsconf.use_straps_for_mode || dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { - nv_connector->native_mode = drm_mode_create(dev); - nouveau_bios_fp_mode(dev, nv_connector->native_mode); + struct drm_display_mode mode; + + nouveau_bios_fp_mode(dev, &mode); + nv_connector->native_mode = drm_mode_duplicate(dev, &mode); } /* Find the native mode if this is a digital panel, if we didn't diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index e424bf74d706..b1be617373b6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1165,6 +1165,7 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); +extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); /* nouveau_fence.c */ struct nouveau_fence; @@ -1388,6 +1389,15 @@ nv_two_reg_pll(struct drm_device *dev) return false; } +static inline bool +nv_match_device(struct drm_device *dev, unsigned device, + unsigned sub_vendor, unsigned sub_device) +{ + return dev->pdev->device == device && + dev->pdev->subsystem_vendor == sub_vendor && + dev->pdev->subsystem_device == sub_device; +} + #define NV_SW 0x0000506e #define NV_SW_DMA_SEMAPHORE 0x00000060 #define NV_SW_SEMAPHORE_OFFSET 0x00000064 diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 6b208ffafa8d..87ac21ec23d2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -64,16 +64,17 @@ nouveau_fence_update(struct nouveau_channel *chan) struct nouveau_fence *fence; uint32_t sequence; + spin_lock(&chan->fence.lock); + if (USE_REFCNT) sequence = nvchan_rd32(chan, 0x48); else sequence = atomic_read(&chan->fence.last_sequence_irq); if (chan->fence.sequence_ack == sequence) - return; + goto out; chan->fence.sequence_ack = sequence; - spin_lock(&chan->fence.lock); list_for_each_safe(entry, tmp, &chan->fence.pending) { fence = list_entry(entry, struct nouveau_fence, entry); @@ -85,6 +86,7 @@ nouveau_fence_update(struct nouveau_channel *chan) if (sequence == chan->fence.sequence_ack) break; } +out: spin_unlock(&chan->fence.lock); } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 0f417ac1b696..19620a6709f5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -167,11 +167,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, goto out; ret = drm_gem_handle_create(file_priv, nvbo->gem, &req->info.handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(nvbo->gem); out: - drm_gem_object_handle_unreference_unlocked(nvbo->gem); - - if (ret) - drm_gem_object_unreference_unlocked(nvbo->gem); return ret; } @@ -245,7 +243,7 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) list_del(&nvbo->entry); nvbo->reserved_by = NULL; ttm_bo_unreserve(&nvbo->bo); - drm_gem_object_unreference(nvbo->gem); + drm_gem_object_unreference_unlocked(nvbo->gem); } } @@ -300,7 +298,7 @@ retry: validate_fini(op, NULL); if (ret == -EAGAIN) ret = ttm_bo_wait_unreserved(&nvbo->bo, false); - drm_gem_object_unreference(gem); + drm_gem_object_unreference_unlocked(gem); if (ret) { NV_ERROR(dev, "fail reserve\n"); return ret; @@ -337,7 +335,9 @@ retry: return -EINVAL; } + mutex_unlock(&drm_global_mutex); ret = ttm_bo_wait_cpu(&nvbo->bo, false); + mutex_lock(&drm_global_mutex); if (ret) { NV_ERROR(dev, "fail wait_cpu\n"); return ret; @@ -361,16 +361,11 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - struct nouveau_fence *prev_fence = nvbo->bo.sync_obj; - if (prev_fence && nouveau_fence_channel(prev_fence) != chan) { - spin_lock(&nvbo->bo.lock); - ret = ttm_bo_wait(&nvbo->bo, false, false, false); - spin_unlock(&nvbo->bo.lock); - if (unlikely(ret)) { - NV_ERROR(dev, "fail wait other chan\n"); - return ret; - } + ret = nouveau_bo_sync_gpu(nvbo, chan); + if (unlikely(ret)) { + NV_ERROR(dev, "fail pre-validate sync\n"); + return ret; } ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains, @@ -381,7 +376,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, return ret; } - nvbo->channel = chan; + nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, false, false, false); nvbo->channel = NULL; @@ -390,6 +385,12 @@ validate_list(struct nouveau_channel *chan, struct list_head *list, return ret; } + ret = nouveau_bo_sync_gpu(nvbo, chan); + if (unlikely(ret)) { + NV_ERROR(dev, "fail post-validate sync\n"); + return ret; + } + if (nvbo->bo.offset == b->presumed.offset && ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || @@ -613,7 +614,20 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, return PTR_ERR(bo); } - mutex_lock(&dev->struct_mutex); + /* Mark push buffers as being used on PFIFO, the validation code + * will then make sure that if the pushbuf bo moves, that they + * happen on the kernel channel, which will in turn cause a sync + * to happen before we try and submit the push buffer. + */ + for (i = 0; i < req->nr_push; i++) { + if (push[i].bo_index >= req->nr_buffers) { + NV_ERROR(dev, "push %d buffer not in list\n", i); + ret = -EINVAL; + goto out; + } + + bo[push[i].bo_index].read_domains |= (1 << 31); + } /* Validate buffer list */ ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, @@ -647,7 +661,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, push[i].length); } } else - if (dev_priv->card_type >= NV_20) { + if (dev_priv->chipset >= 0x25) { ret = RING_SPACE(chan, req->nr_push * 2); if (ret) { NV_ERROR(dev, "cal_space: %d\n", ret); @@ -713,7 +727,6 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, out: validate_fini(&op, fence); nouveau_fence_unref((void**)&fence); - mutex_unlock(&dev->struct_mutex); kfree(bo); kfree(push); @@ -722,7 +735,7 @@ out_next: req->suffix0 = 0x00000000; req->suffix1 = 0x00000000; } else - if (dev_priv->card_type >= NV_20) { + if (dev_priv->chipset >= 0x25) { req->suffix0 = 0x00020000; req->suffix1 = 0x00000000; } else { diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 0bd407ca3d42..84614858728b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) if (entry->chan) return -EEXIST; - if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) { + if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { NV_ERROR(dev, "unknown i2c port %d\n", entry->read); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 491767fe4fcf..6b9187d7f67d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -214,6 +214,7 @@ int nouveau_sgdma_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct pci_dev *pdev = dev->pdev; struct nouveau_gpuobj *gpuobj = NULL; uint32_t aper_size, obj_size; int i, ret; @@ -239,10 +240,19 @@ nouveau_sgdma_init(struct drm_device *dev) dev_priv->gart_info.sg_dummy_page = alloc_page(GFP_KERNEL|__GFP_DMA32); + if (!dev_priv->gart_info.sg_dummy_page) { + nouveau_gpuobj_del(dev, &gpuobj); + return -ENOMEM; + } + set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags); dev_priv->gart_info.sg_dummy_bus = - pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0, + pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { + nouveau_gpuobj_del(dev, &gpuobj); + return -EFAULT; + } if (dev_priv->card_type < NV_50) { /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index a5dcf7685800..0d3206a7046c 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -444,6 +444,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct dcb_entry *dcbe = nv_encoder->dcb; int head = nouveau_crtc(encoder->crtc)->index; + struct drm_encoder *slave_encoder; if (dcbe->type == OUTPUT_TMDS) run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); @@ -462,9 +463,10 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); /* Init external transmitters */ - if (get_tmds_slave(encoder)) - get_slave_funcs(get_tmds_slave(encoder))->mode_set( - encoder, &nv_encoder->mode, &nv_encoder->mode); + slave_encoder = get_tmds_slave(encoder); + if (slave_encoder) + get_slave_funcs(slave_encoder)->mode_set( + slave_encoder, &nv_encoder->mode, &nv_encoder->mode); helper->dpms(encoder, DRM_MODE_DPMS_ON); @@ -473,6 +475,27 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } +static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) +{ +#ifdef __powerpc__ + struct drm_device *dev = encoder->dev; + + /* BIOS scripts usually take care of the backlight, thanks + * Apple for your consistency. + */ + if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || + dev->pci_device == 0x0329) { + if (mode == DRM_MODE_DPMS_ON) { + nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); + nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 1); + } else { + nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); + nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 0); + } + } +#endif +} + static inline bool is_powersaving_dpms(int mode) { return (mode != DRM_MODE_DPMS_ON); @@ -520,6 +543,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) LVDS_PANEL_OFF, 0); } + nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_fp_control(encoder, mode); if (mode == DRM_MODE_DPMS_ON) @@ -543,6 +567,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", mode, nv_encoder->dcb->index); + nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_fp_control(encoder, mode); } diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 44fefb0c7083..13cdc05b7c2d 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -121,10 +121,14 @@ static bool get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) { /* Zotac FX5200 */ - if (dev->pdev->device == 0x0322 && - dev->pdev->subsystem_vendor == 0x19da && - (dev->pdev->subsystem_device == 0x1035 || - dev->pdev->subsystem_device == 0x2035)) { + if (nv_match_device(dev, 0x0322, 0x19da, 0x1035) || + nv_match_device(dev, 0x0322, 0x19da, 0x2035)) { + *pin_mask = 0xc; + return false; + } + + /* MSI nForce2 IGP */ + if (nv_match_device(dev, 0x01f0, 0x1462, 0x5710)) { *pin_mask = 0xc; return false; } diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index 37c7b48ab24a..91ef93cf1f35 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -139,6 +139,8 @@ nv50_instmem_init(struct drm_device *dev) chan->file_priv = (struct drm_file *)-2; dev_priv->fifos[0] = dev_priv->fifos[127] = chan; + INIT_LIST_HEAD(&chan->ramht_refs); + /* Channel's PRAMIN object + heap */ ret = nouveau_gpuobj_new_fake(dev, 0, c_offset, c_size, 0, NULL, &chan->ramin); @@ -278,7 +280,7 @@ nv50_instmem_init(struct drm_device *dev) /*XXX: incorrect, but needed to make hash func "work" */ dev_priv->ramht_offset = 0x10000; dev_priv->ramht_bits = 9; - dev_priv->ramht_size = (1 << dev_priv->ramht_bits); + dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c index 3ab3cdc42173..6b451f864783 100644 --- a/drivers/gpu/drm/nouveau/nvc0_instmem.c +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c @@ -142,14 +142,16 @@ int nvc0_instmem_suspend(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 *buf; int i; dev_priv->susres.ramin_copy = vmalloc(65536); if (!dev_priv->susres.ramin_copy) return -ENOMEM; + buf = dev_priv->susres.ramin_copy; - for (i = 0x700000; i < 0x710000; i += 4) - dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i); + for (i = 0; i < 65536; i += 4) + buf[i/4] = nv_rd32(dev, NV04_PRAMIN + i); return 0; } @@ -157,14 +159,15 @@ void nvc0_instmem_resume(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 *buf = dev_priv->susres.ramin_copy; u64 chan; int i; chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; nv_wr32(dev, 0x001700, chan >> 16); - for (i = 0x700000; i < 0x710000; i += 4) - nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]); + for (i = 0; i < 65536; i += 4) + nv_wr32(dev, NV04_PRAMIN + i, buf[i/4]); vfree(dev_priv->susres.ramin_copy); dev_priv->susres.ramin_copy = NULL; @@ -221,7 +224,7 @@ nvc0_instmem_init(struct drm_device *dev) /*XXX: incorrect, but needed to make hash func "work" */ dev_priv->ramht_offset = 0x10000; dev_priv->ramht_bits = 9; - dev_priv->ramht_size = (1 << dev_priv->ramht_bits); + dev_priv->ramht_size = (1 << dev_priv->ramht_bits) * 8; return 0; } diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c index 077af1f2f9b4..a9e33ce65918 100644 --- a/drivers/gpu/drm/r128/r128_state.c +++ b/drivers/gpu/drm/r128/r128_state.c @@ -1639,30 +1639,29 @@ void r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) r128_do_cleanup_pageflip(dev); } } - void r128_driver_lastclose(struct drm_device *dev) { r128_do_cleanup_cce(dev); } struct drm_ioctl_desc r128_ioctls[] = { - DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH), - DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH), + DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH), }; int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 1bc72c3190a9..fe359a239df3 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -4999,7 +4999,7 @@ typedef struct _SW_I2C_IO_DATA_PARAMETERS #define SW_I2C_CNTL_WRITE1BIT 6 //==============================VESA definition Portion=============================== -#define VESA_OEM_PRODUCT_REV '01.00' +#define VESA_OEM_PRODUCT_REV "01.00" #define VESA_MODE_ATTRIBUTE_MODE_SUPPORT 0xBB //refer to VBE spec p.32, no TTY support #define VESA_MODE_WIN_ATTRIBUTE 7 #define VESA_WIN_SIZE 64 diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 12ad512bd3d3..cd0290f946cf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -332,6 +332,11 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, args.usV_SyncWidth = cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start); + args.ucOverscanRight = radeon_crtc->h_border; + args.ucOverscanLeft = radeon_crtc->h_border; + args.ucOverscanBottom = radeon_crtc->v_border; + args.ucOverscanTop = radeon_crtc->v_border; + if (mode->flags & DRM_MODE_FLAG_NVSYNC) misc |= ATOM_VSYNC_POLARITY; if (mode->flags & DRM_MODE_FLAG_NHSYNC) @@ -471,6 +476,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, struct radeon_encoder *radeon_encoder = NULL; u32 adjusted_clock = mode->clock; int encoder_mode = 0; + u32 dp_clock = mode->clock; + int bpc = 8; /* reset the pll flags */ pll->flags = 0; @@ -513,6 +520,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if (encoder->crtc == crtc) { radeon_encoder = to_radeon_encoder(encoder); encoder_mode = atombios_get_encoder_mode(encoder); + if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + dp_clock = dig_connector->dp_clock; + } + } + if (ASIC_IS_AVIVO(rdev)) { /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) @@ -521,6 +539,21 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, pll->algo = PLL_ALGO_LEGACY; pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; } + /* There is some evidence (often anecdotal) that RV515/RV620 LVDS + * (on some boards at least) prefers the legacy algo. I'm not + * sure whether this should handled generically or on a + * case-by-case quirk basis. Both algos should work fine in the + * majority of cases. + */ + if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && + ((rdev->family == CHIP_RV515) || + (rdev->family == CHIP_RV620))) { + /* allow the user to overrride just in case */ + if (radeon_new_pll == 1) + pll->algo = PLL_ALGO_NEW; + else + pll->algo = PLL_ALGO_LEGACY; + } } else { if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; @@ -555,6 +588,14 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); args.v1.ucTransmitterID = radeon_encoder->encoder_id; args.v1.ucEncodeMode = encoder_mode; + if (encoder_mode == ATOM_ENCODER_MODE_DP) { + /* may want to enable SS on DP eventually */ + /* args.v1.ucConfig |= + ADJUST_DISPLAY_CONFIG_SS_ENABLE;*/ + } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { + args.v1.ucConfig |= + ADJUST_DISPLAY_CONFIG_SS_ENABLE; + } atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); @@ -568,10 +609,20 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - if (encoder_mode == ATOM_ENCODER_MODE_DP) + if (encoder_mode == ATOM_ENCODER_MODE_DP) { + /* may want to enable SS on DP/eDP eventually */ + /*args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_SS_ENABLE;*/ args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; - else { + /* 16200 or 27000 */ + args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); + } else { + if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { + /* deep color support */ + args.v3.sInput.usPixelClock = + cpu_to_le16((mode->clock * bpc / 8) / 10); + } if (dig->coherent_mode) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; @@ -580,13 +631,19 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, DISPPLL_CONFIG_DUAL_LINK; } } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { - /* may want to enable SS on DP/eDP eventually */ - /*args.v3.sInput.ucDispPllConfig |= - DISPPLL_CONFIG_SS_ENABLE;*/ - if (encoder_mode == ATOM_ENCODER_MODE_DP) + if (encoder_mode == ATOM_ENCODER_MODE_DP) { + /* may want to enable SS on DP/eDP eventually */ + /*args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_SS_ENABLE;*/ args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_COHERENT_MODE; - else { + /* 16200 or 27000 */ + args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); + } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { + /* want to enable SS on LVDS eventually */ + /*args.v3.sInput.ucDispPllConfig |= + DISPPLL_CONFIG_SS_ENABLE;*/ + } else { if (mode->clock > 165000) args.v3.sInput.ucDispPllConfig |= DISPPLL_CONFIG_DUAL_LINK; @@ -1019,11 +1076,11 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, if (rdev->family >= CHIP_RV770) { if (radeon_crtc->crtc_id) { - WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); - WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); + WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); } else { - WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); - WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); + WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); + WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); } } WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, @@ -1160,8 +1217,18 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + struct drm_encoder *encoder; + bool is_tvcv = false; - /* TODO color tiling */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + /* find tv std */ + if (encoder->crtc == crtc) { + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + if (radeon_encoder->active_device & + (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) + is_tvcv = true; + } + } atombios_disable_ss(crtc); /* always set DCPLL */ @@ -1170,9 +1237,14 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, atombios_crtc_set_pll(crtc, adjusted_mode); atombios_enable_ss(crtc); - if (ASIC_IS_AVIVO(rdev)) + if (ASIC_IS_DCE4(rdev)) atombios_set_crtc_dtd_timing(crtc, adjusted_mode); - else { + else if (ASIC_IS_AVIVO(rdev)) { + if (is_tvcv) + atombios_crtc_set_timing(crtc, adjusted_mode); + else + atombios_set_crtc_dtd_timing(crtc, adjusted_mode); + } else { atombios_crtc_set_timing(crtc, adjusted_mode); if (radeon_crtc->crtc_id == 0) atombios_set_crtc_dtd_timing(crtc, adjusted_mode); diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 36e0d4b545e6..4e7778d44b8d 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -610,7 +610,7 @@ void dp_link_train(struct drm_encoder *encoder, enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; else enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; - if (dig_connector->linkb) + if (dig->linkb) enc_id |= ATOM_DP_CONFIG_LINK_B; else enc_id |= ATOM_DP_CONFIG_LINK_A; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 957d5067ad9c..2f93d46ae69a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -675,6 +675,43 @@ static int evergreen_cp_load_microcode(struct radeon_device *rdev) return 0; } +static int evergreen_cp_start(struct radeon_device *rdev) +{ + int r; + uint32_t cp_me; + + r = radeon_ring_lock(rdev, 7); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); + radeon_ring_write(rdev, 0x1); + radeon_ring_write(rdev, 0x0); + radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); + radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); + radeon_ring_write(rdev, 0); + radeon_ring_write(rdev, 0); + radeon_ring_unlock_commit(rdev); + + cp_me = 0xff; + WREG32(CP_ME_CNTL, cp_me); + + r = radeon_ring_lock(rdev, 4); + if (r) { + DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); + return r; + } + /* init some VGT regs */ + radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONTEXT_REG, 2)); + radeon_ring_write(rdev, (VGT_VERTEX_REUSE_BLOCK_CNTL - PACKET3_SET_CONTEXT_REG_START) >> 2); + radeon_ring_write(rdev, 0xe); + radeon_ring_write(rdev, 0x10); + radeon_ring_unlock_commit(rdev); + + return 0; +} + int evergreen_cp_resume(struct radeon_device *rdev) { u32 tmp; @@ -719,7 +756,7 @@ int evergreen_cp_resume(struct radeon_device *rdev) rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); - r600_cp_start(rdev); + evergreen_cp_start(rdev); rdev->cp.ready = true; r = radeon_ring_test(rdev); if (r) { @@ -1100,7 +1137,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(RCU_IND_INDEX, 0x203); efuse_straps_3 = RREG32(RCU_IND_DATA); - efuse_box_bit_127_124 = (u8)(efuse_straps_3 & 0xF0000000) >> 28; + efuse_box_bit_127_124 = (u8)((efuse_straps_3 & 0xF0000000) >> 28); switch(efuse_box_bit_127_124) { case 0x0: @@ -1123,14 +1160,25 @@ static void evergreen_gpu_init(struct radeon_device *rdev) EVERGREEN_MAX_BACKENDS_MASK)); break; } - } else - gb_backend_map = - evergreen_get_tile_pipe_to_backend_map(rdev, - rdev->config.evergreen.max_tile_pipes, - rdev->config.evergreen.max_backends, - ((EVERGREEN_MAX_BACKENDS_MASK << - rdev->config.evergreen.max_backends) & - EVERGREEN_MAX_BACKENDS_MASK)); + } else { + switch (rdev->family) { + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + gb_backend_map = 0x66442200; + break; + case CHIP_JUNIPER: + gb_backend_map = 0x00006420; + break; + default: + gb_backend_map = + evergreen_get_tile_pipe_to_backend_map(rdev, + rdev->config.evergreen.max_tile_pipes, + rdev->config.evergreen.max_backends, + ((EVERGREEN_MAX_BACKENDS_MASK << + rdev->config.evergreen.max_backends) & + EVERGREEN_MAX_BACKENDS_MASK)); + } + } rdev->config.evergreen.tile_config = gb_addr_config; WREG32(GB_BACKEND_MAP, gb_backend_map); @@ -1359,6 +1407,7 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); @@ -1472,7 +1521,7 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev) { u32 tmp; - WREG32(CP_INT_CNTL, 0); + WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(GRBM_INT_CNTL, 0); WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); @@ -2054,11 +2103,6 @@ int evergreen_resume(struct radeon_device *rdev) */ /* post card */ atom_asic_init(rdev->mode_info.atom_context); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } r = evergreen_startup(rdev); if (r) { @@ -2164,9 +2208,6 @@ int evergreen_init(struct radeon_device *rdev) radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); - r = radeon_clocks_init(rdev); - if (r) - return r; /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) @@ -2236,7 +2277,6 @@ void evergreen_fini(struct radeon_device *rdev) evergreen_pcie_gart_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); radeon_agp_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index e817a0bb5eb4..e59422320bb6 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1030,6 +1030,7 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) return r; } rdev->cp.ready = true; + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -1047,6 +1048,7 @@ void r100_cp_fini(struct radeon_device *rdev) void r100_cp_disable(struct radeon_device *rdev) { /* Disable ring */ + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->cp.ready = false; WREG32(RADEON_CP_CSQ_MODE, 0); WREG32(RADEON_CP_CSQ_CNTL, 0); @@ -2020,18 +2022,7 @@ bool r100_gpu_cp_is_lockup(struct radeon_device *rdev, struct r100_gpu_lockup *l return false; } elapsed = jiffies_to_msecs(cjiffies - lockup->last_jiffies); - if (elapsed >= 3000) { - /* very likely the improbable case where current - * rptr is equal to last recorded, a while ago, rptr - * this is more likely a false positive update tracking - * information which should force us to be recall at - * latter point - */ - lockup->last_cp_rptr = cp->rptr; - lockup->last_jiffies = jiffies; - return false; - } - if (elapsed >= 1000) { + if (elapsed >= 10000) { dev_err(rdev->dev, "GPU lockup CP stall for more than %lumsec\n", elapsed); return true; } @@ -2306,6 +2297,7 @@ void r100_vram_init_sizes(struct radeon_device *rdev) /* FIXME we don't use the second aperture yet when we could use it */ if (rdev->mc.visible_vram_size > rdev->mc.aper_size) rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); if (rdev->flags & RADEON_IS_IGP) { uint32_t tom; @@ -3308,13 +3300,14 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) unsigned long size; unsigned prim_walk; unsigned nverts; + unsigned num_cb = track->num_cb; - for (i = 0; i < track->num_cb; i++) { + if (!track->zb_cb_clear && !track->color_channel_mask && + !track->blend_read_enable) + num_cb = 0; + + for (i = 0; i < num_cb; i++) { if (track->cb[i].robj == NULL) { - if (!(track->zb_cb_clear || track->color_channel_mask || - track->blend_read_enable)) { - continue; - } DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); return -EINVAL; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index d0ebae9dde25..7b65e4efe8af 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1248,6 +1248,7 @@ int r600_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); if (rdev->flags & RADEON_IS_IGP) { @@ -1917,6 +1918,7 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) */ void r600_cp_stop(struct radeon_device *rdev) { + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); } @@ -2119,10 +2121,7 @@ int r600_cp_start(struct radeon_device *rdev) } radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5)); radeon_ring_write(rdev, 0x1); - if (rdev->family >= CHIP_CEDAR) { - radeon_ring_write(rdev, 0x0); - radeon_ring_write(rdev, rdev->config.evergreen.max_hw_contexts - 1); - } else if (rdev->family >= CHIP_RV770) { + if (rdev->family >= CHIP_RV770) { radeon_ring_write(rdev, 0x0); radeon_ring_write(rdev, rdev->config.rv770.max_hw_contexts - 1); } else { @@ -2489,11 +2488,6 @@ int r600_resume(struct radeon_device *rdev) */ /* post card */ atom_asic_init(rdev->mode_info.atom_context); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } r = r600_startup(rdev); if (r) { @@ -2586,9 +2580,6 @@ int r600_init(struct radeon_device *rdev) radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); - r = radeon_clocks_init(rdev); - if (r) - return r; /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) @@ -2663,7 +2654,6 @@ void r600_fini(struct radeon_device *rdev) radeon_agp_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); @@ -2741,7 +2731,7 @@ int r600_ib_test(struct radeon_device *rdev) if (i < rdev->usec_timeout) { DRM_INFO("ib test succeeded in %u usecs\n", i); } else { - DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n", + DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", scratch, tmp); r = -EINVAL; } @@ -2922,7 +2912,7 @@ static void r600_disable_interrupt_state(struct radeon_device *rdev) { u32 tmp; - WREG32(CP_INT_CNTL, 0); + WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(GRBM_INT_CNTL, 0); WREG32(DxMODE_INT_MASK, 0); if (ASIC_IS_DCE3(rdev)) { @@ -3540,8 +3530,9 @@ void r600_ioctl_wait_idle(struct radeon_device *rdev, struct radeon_bo *bo) /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL */ - if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740)) { - void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; + if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && + rdev->vram_scratch.ptr) { + void __iomem *ptr = (void *)rdev->vram_scratch.ptr; u32 tmp; WREG32(HDP_DEBUG1, 0); diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index d13622ae74e9..3473c00781ff 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -1,3 +1,28 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + #include "drmP.h" #include "drm.h" #include "radeon_drm.h" @@ -507,6 +532,7 @@ int r600_blit_init(struct radeon_device *rdev) memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4); radeon_bo_kunmap(rdev->r600_blit.shader_obj); radeon_bo_unreserve(rdev->r600_blit.shader_obj); + rdev->mc.active_vram_size = rdev->mc.real_vram_size; return 0; } @@ -514,6 +540,7 @@ void r600_blit_fini(struct radeon_device *rdev) { int r; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; if (rdev->r600_blit.shader_obj == NULL) return; /* If we can't reserve the bo, unref should be enough to destroy diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.h b/drivers/gpu/drm/radeon/r600_blit_shaders.h index fdc3b378cbb0..f437d36dd98c 100644 --- a/drivers/gpu/drm/radeon/r600_blit_shaders.h +++ b/drivers/gpu/drm/radeon/r600_blit_shaders.h @@ -1,3 +1,27 @@ +/* + * Copyright 2009 Advanced Micro Devices, Inc. + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ #ifndef R600_BLIT_SHADERS_H #define R600_BLIT_SHADERS_H diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index d8864949e387..250a3a918193 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -1170,9 +1170,8 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p, u32 i /* using get ib will give us the offset into the mipmap bo */ word0 = radeon_get_ib_value(p, idx + 3) << 8; if ((mipmap_size + word0) > radeon_bo_size(mipmap)) { - dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", - w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture)); - return -EINVAL; + /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n", + w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/ } return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3dfcfa3ca425..9ff38c99a6ea 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -344,6 +344,7 @@ struct radeon_mc { * about vram size near mc fb location */ u64 mc_vram_size; u64 visible_vram_size; + u64 active_vram_size; u64 gtt_size; u64 gtt_start; u64 gtt_end; @@ -1013,6 +1014,11 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +/* VRAM scratch page for HDP bug */ +struct r700_vram_scratch { + struct radeon_bo *robj; + volatile uint32_t *ptr; +}; /* * Core structure, functions and helpers. @@ -1079,6 +1085,7 @@ struct radeon_device { const struct firmware *pfp_fw; /* r6/700 PFP firmware */ const struct firmware *rlc_fw; /* r6/700 RLC firmware */ struct r600_blit r600_blit; + struct r700_vram_scratch vram_scratch; int msi_enabled; /* msi enabled */ struct r600_ih ih; /* r6/700 interrupt ring */ struct workqueue_struct *wq; @@ -1333,8 +1340,6 @@ extern bool radeon_card_posted(struct radeon_device *rdev); extern void radeon_update_bandwidth_info(struct radeon_device *rdev); extern void radeon_update_display_priority(struct radeon_device *rdev); extern bool radeon_boot_test_post_card(struct radeon_device *rdev); -extern int radeon_clocks_init(struct radeon_device *rdev); -extern void radeon_clocks_fini(struct radeon_device *rdev); extern void radeon_scratch_init(struct radeon_device *rdev); extern void radeon_surface_init(struct radeon_device *rdev); extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data); diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index f40dfb77f9b1..bd2f33e5c91a 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -156,7 +156,13 @@ int radeon_agp_init(struct radeon_device *rdev) } mode.mode = info.mode; - agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode; + /* chips with the agp to pcie bridge don't have the AGP_STATUS register + * Just use the whatever mode the host sets up. + */ + if (rdev->family <= CHIP_RV350) + agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode; + else + agp_status = mode.mode; is_v3 = !!(agp_status & RADEON_AGPv3_MODE); if (is_v3) { diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 646f96f97c77..25e1dd197791 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -733,6 +733,7 @@ static struct radeon_asic evergreen_asic = { .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock, + .get_pcie_lanes = NULL, .set_pcie_lanes = NULL, .set_clock_gating = NULL, .set_surface_reg = r600_set_surface_reg, @@ -857,21 +858,3 @@ int radeon_asic_init(struct radeon_device *rdev) return 0; } -/* - * Wrapper around modesetting bits. Move to radeon_clocks.c? - */ -int radeon_clocks_init(struct radeon_device *rdev) -{ - int r; - - r = radeon_static_clocks_init(rdev->ddev); - if (r) { - return r; - } - DRM_INFO("Clocks initialized !\n"); - return 0; -} - -void radeon_clocks_fini(struct radeon_device *rdev) -{ -} diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 6d30868744ee..8e43ddae70cc 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -32,11 +32,11 @@ /* from radeon_encoder.c */ extern uint32_t -radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, - uint8_t dac); +radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, + uint8_t dac); extern void radeon_link_encoder_connector(struct drm_device *dev); extern void -radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, +radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device); /* from radeon_connector.c */ @@ -46,14 +46,14 @@ radeon_add_atom_connector(struct drm_device *dev, uint32_t supported_device, int connector_type, struct radeon_i2c_bus_rec *i2c_bus, - bool linkb, uint32_t igp_lane_info, + uint32_t igp_lane_info, uint16_t connector_object_id, struct radeon_hpd *hpd, struct radeon_router *router); /* from radeon_legacy_encoder.c */ extern void -radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, +radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device); union atom_supported_devices { @@ -85,6 +85,19 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; + /* some evergreen boards have bad data for this entry */ + if (ASIC_IS_DCE4(rdev)) { + if ((i == 7) && + (gpio->usClkMaskRegisterIndex == 0x1936) && + (gpio->sucI2cId.ucAccess == 0)) { + gpio->sucI2cId.ucAccess = 0x97; + gpio->ucDataMaskShift = 8; + gpio->ucDataEnShift = 8; + gpio->ucDataY_Shift = 8; + gpio->ucDataA_Shift = 8; + } + } + if (gpio->sucI2cId.ucAccess == id) { i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; @@ -147,6 +160,20 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev) for (i = 0; i < num_indices; i++) { gpio = &i2c_info->asGPIO_Info[i]; i2c.valid = false; + + /* some evergreen boards have bad data for this entry */ + if (ASIC_IS_DCE4(rdev)) { + if ((i == 7) && + (gpio->usClkMaskRegisterIndex == 0x1936) && + (gpio->sucI2cId.ucAccess == 0)) { + gpio->sucI2cId.ucAccess = 0x97; + gpio->ucDataMaskShift = 8; + gpio->ucDataEnShift = 8; + gpio->ucDataY_Shift = 8; + gpio->ucDataA_Shift = 8; + } + } + i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4; i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4; i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4; @@ -226,6 +253,8 @@ static struct radeon_hpd radeon_atom_get_hpd_info_from_gpio(struct radeon_device struct radeon_hpd hpd; u32 reg; + memset(&hpd, 0, sizeof(struct radeon_hpd)); + if (ASIC_IS_DCE4(rdev)) reg = EVERGREEN_DC_GPIO_HPD_A; else @@ -288,6 +317,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, *connector_type = DRM_MODE_CONNECTOR_DVID; } + /* MSI K9A2GM V2/V3 board has no HDMI or DVI */ + if ((dev->pdev->device == 0x796e) && + (dev->pdev->subsystem_vendor == 0x1462) && + (dev->pdev->subsystem_device == 0x7302)) { + if ((supported_device == ATOM_DEVICE_DFP2_SUPPORT) || + (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) + return false; + } + /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ if ((dev->pdev->device == 0x7941) && (dev->pdev->subsystem_vendor == 0x147b) && @@ -477,7 +515,6 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) int i, j, k, path_size, device_support; int connector_type; u16 igp_lane_info, conn_id, connector_object_id; - bool linkb; struct radeon_i2c_bus_rec ddc_bus; struct radeon_router router; struct radeon_gpio_rec gpio; @@ -510,7 +547,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) addr += path_size; path = (ATOM_DISPLAY_OBJECT_PATH *) addr; path_size += le16_to_cpu(path->usSize); - linkb = false; + if (device_support & le16_to_cpu(path->usDeviceTag)) { uint8_t con_obj_id, con_obj_num, con_obj_type; @@ -601,13 +638,10 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; if (grph_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { - if (grph_obj_num == 2) - linkb = true; - else - linkb = false; + u16 encoder_obj = le16_to_cpu(path->usGraphicObjIds[j]); radeon_add_atom_encoder(dev, - grph_obj_id, + encoder_obj, le16_to_cpu (path-> usDeviceTag)); @@ -744,7 +778,7 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) le16_to_cpu(path-> usDeviceTag), connector_type, &ddc_bus, - linkb, igp_lane_info, + igp_lane_info, connector_object_id, &hpd, &router); @@ -933,13 +967,13 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) radeon_add_atom_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, (1 << i), dac), (1 << i)); else radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, (1 << i), dac), (1 << i)); @@ -996,7 +1030,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct bios_connectors[i]. connector_type, &bios_connectors[i].ddc_bus, - false, 0, + 0, connector_object_id, &bios_connectors[i].hpd, &router); @@ -1183,7 +1217,7 @@ bool radeon_atombios_sideport_present(struct radeon_device *rdev) return true; break; case 2: - if (igp_info->info_2.ucMemoryType & 0x0f) + if (igp_info->info_2.ulBootUpSidePortClock) return true; break; default: @@ -1305,6 +1339,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct union lvds_info *lvds_info; uint8_t frev, crev; struct radeon_encoder_atom_dig *lvds = NULL; + int encoder_enum = (encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; if (atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset)) { @@ -1368,6 +1403,12 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct } encoder->native_mode = lvds->native_mode; + + if (encoder_enum == 2) + lvds->linkb = true; + else + lvds->linkb = false; + } return lvds; } @@ -1517,39 +1558,39 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev) switch (tv_info->ucTV_BootUpDefaultStandard) { case ATOM_TV_NTSC: tv_std = TV_STD_NTSC; - DRM_INFO("Default TV standard: NTSC\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC\n"); break; case ATOM_TV_NTSCJ: tv_std = TV_STD_NTSC_J; - DRM_INFO("Default TV standard: NTSC-J\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); break; case ATOM_TV_PAL: tv_std = TV_STD_PAL; - DRM_INFO("Default TV standard: PAL\n"); + DRM_DEBUG_KMS("Default TV standard: PAL\n"); break; case ATOM_TV_PALM: tv_std = TV_STD_PAL_M; - DRM_INFO("Default TV standard: PAL-M\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); break; case ATOM_TV_PALN: tv_std = TV_STD_PAL_N; - DRM_INFO("Default TV standard: PAL-N\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-N\n"); break; case ATOM_TV_PALCN: tv_std = TV_STD_PAL_CN; - DRM_INFO("Default TV standard: PAL-CN\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-CN\n"); break; case ATOM_TV_PAL60: tv_std = TV_STD_PAL_60; - DRM_INFO("Default TV standard: PAL-60\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); break; case ATOM_TV_SECAM: tv_std = TV_STD_SECAM; - DRM_INFO("Default TV standard: SECAM\n"); + DRM_DEBUG_KMS("Default TV standard: SECAM\n"); break; default: tv_std = TV_STD_NTSC; - DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); + DRM_DEBUG_KMS("Unknown TV standard; defaulting to NTSC\n"); break; } } diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 14448a740ba6..5249af8931e6 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -327,6 +327,14 @@ void radeon_get_clock_info(struct drm_device *dev) mpll->max_feedback_div = 0xff; mpll->best_vco = 0; + if (!rdev->clock.default_sclk) + rdev->clock.default_sclk = radeon_get_engine_clock(rdev); + if ((!rdev->clock.default_mclk) && rdev->asic->get_memory_clock) + rdev->clock.default_mclk = radeon_get_memory_clock(rdev); + + rdev->pm.current_sclk = rdev->clock.default_sclk; + rdev->pm.current_mclk = rdev->clock.default_mclk; + } /* 10 khz */ @@ -897,53 +905,3 @@ void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) } } -static void radeon_apply_clock_quirks(struct radeon_device *rdev) -{ - uint32_t tmp; - - /* XXX make sure engine is idle */ - - if (rdev->family < CHIP_RS600) { - tmp = RREG32_PLL(RADEON_SCLK_CNTL); - if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev)) - tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; - if ((rdev->family == CHIP_RV250) - || (rdev->family == CHIP_RV280)) - tmp |= - RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2; - if ((rdev->family == CHIP_RV350) - || (rdev->family == CHIP_RV380)) - tmp |= R300_SCLK_FORCE_VAP; - if (rdev->family == CHIP_R420) - tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX; - WREG32_PLL(RADEON_SCLK_CNTL, tmp); - } else if (rdev->family < CHIP_R600) { - tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL); - tmp |= AVIVO_CP_FORCEON; - WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp); - - tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL); - tmp |= AVIVO_E2_FORCEON; - WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp); - - tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL); - tmp |= AVIVO_IDCT_FORCEON; - WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp); - } -} - -int radeon_static_clocks_init(struct drm_device *dev) -{ - struct radeon_device *rdev = dev->dev_private; - - /* XXX make sure engine is idle */ - - if (radeon_dynclks != -1) { - if (radeon_dynclks) { - if (rdev->asic->set_clock_gating) - radeon_set_clock_gating(rdev, 1); - } - } - radeon_apply_clock_quirks(rdev); - return 0; -} diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 885dcfac1838..7b7ea269549c 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -39,8 +39,8 @@ /* from radeon_encoder.c */ extern uint32_t -radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, - uint8_t dac); +radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, + uint8_t dac); extern void radeon_link_encoder_connector(struct drm_device *dev); /* from radeon_connector.c */ @@ -55,7 +55,7 @@ radeon_add_legacy_connector(struct drm_device *dev, /* from radeon_legacy_encoder.c */ extern void -radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, +radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device); /* old legacy ATI BIOS routines */ @@ -913,47 +913,47 @@ radeon_combios_get_tv_info(struct radeon_device *rdev) switch (RBIOS8(tv_info + 7) & 0xf) { case 1: tv_std = TV_STD_NTSC; - DRM_INFO("Default TV standard: NTSC\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC\n"); break; case 2: tv_std = TV_STD_PAL; - DRM_INFO("Default TV standard: PAL\n"); + DRM_DEBUG_KMS("Default TV standard: PAL\n"); break; case 3: tv_std = TV_STD_PAL_M; - DRM_INFO("Default TV standard: PAL-M\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-M\n"); break; case 4: tv_std = TV_STD_PAL_60; - DRM_INFO("Default TV standard: PAL-60\n"); + DRM_DEBUG_KMS("Default TV standard: PAL-60\n"); break; case 5: tv_std = TV_STD_NTSC_J; - DRM_INFO("Default TV standard: NTSC-J\n"); + DRM_DEBUG_KMS("Default TV standard: NTSC-J\n"); break; case 6: tv_std = TV_STD_SCART_PAL; - DRM_INFO("Default TV standard: SCART-PAL\n"); + DRM_DEBUG_KMS("Default TV standard: SCART-PAL\n"); break; default: tv_std = TV_STD_NTSC; - DRM_INFO + DRM_DEBUG_KMS ("Unknown TV standard; defaulting to NTSC\n"); break; } switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) { case 0: - DRM_INFO("29.498928713 MHz TV ref clk\n"); + DRM_DEBUG_KMS("29.498928713 MHz TV ref clk\n"); break; case 1: - DRM_INFO("28.636360000 MHz TV ref clk\n"); + DRM_DEBUG_KMS("28.636360000 MHz TV ref clk\n"); break; case 2: - DRM_INFO("14.318180000 MHz TV ref clk\n"); + DRM_DEBUG_KMS("14.318180000 MHz TV ref clk\n"); break; case 3: - DRM_INFO("27.000000000 MHz TV ref clk\n"); + DRM_DEBUG_KMS("27.000000000 MHz TV ref clk\n"); break; default: break; @@ -1324,7 +1324,7 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder, if (tmds_info) { ver = RBIOS8(tmds_info); - DRM_INFO("DFP table revision: %d\n", ver); + DRM_DEBUG_KMS("DFP table revision: %d\n", ver); if (ver == 3) { n = RBIOS8(tmds_info + 5) + 1; if (n > 4) @@ -1408,7 +1408,7 @@ bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); if (offset) { ver = RBIOS8(offset); - DRM_INFO("External TMDS Table revision: %d\n", ver); + DRM_DEBUG_KMS("External TMDS Table revision: %d\n", ver); tmds->slave_addr = RBIOS8(offset + 4 + 2); tmds->slave_addr >>= 1; /* 7 bit addressing */ gpio = RBIOS8(offset + 4 + 3); @@ -1485,6 +1485,11 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) /* PowerMac8,1 ? */ /* imac g5 isight */ rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; + } else if ((rdev->pdev->device == 0x4a48) && + (rdev->pdev->subsystem_vendor == 0x1002) && + (rdev->pdev->subsystem_device == 0x4a48)) { + /* Mac X800 */ + rdev->mode_info.connector_table = CT_MAC_X800; } else #endif /* CONFIG_PPC_PMAC */ #ifdef CONFIG_PPC64 @@ -1505,7 +1510,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1520,7 +1525,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_NONE_DETECTED, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_LCD1_SUPPORT, 0), ATOM_DEVICE_LCD1_SUPPORT); @@ -1535,7 +1540,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1550,12 +1555,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_1; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP1_SUPPORT, 0), ATOM_DEVICE_DFP1_SUPPORT); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1571,7 +1576,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1588,7 +1593,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1607,7 +1612,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_LCD1_SUPPORT, 0), ATOM_DEVICE_LCD1_SUPPORT); @@ -1619,7 +1624,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1631,7 +1636,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1648,7 +1653,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_LCD1_SUPPORT, 0), ATOM_DEVICE_LCD1_SUPPORT); @@ -1660,12 +1665,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_2; /* ??? */ radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP2_SUPPORT, 0), ATOM_DEVICE_DFP2_SUPPORT); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1680,7 +1685,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1697,7 +1702,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_LCD1_SUPPORT, 0), ATOM_DEVICE_LCD1_SUPPORT); @@ -1709,12 +1714,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP1_SUPPORT, 0), ATOM_DEVICE_DFP1_SUPPORT); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1728,7 +1733,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1745,7 +1750,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_LCD1_SUPPORT, 0), ATOM_DEVICE_LCD1_SUPPORT); @@ -1757,7 +1762,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1769,7 +1774,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1786,12 +1791,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_2; /* ??? */ radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP2_SUPPORT, 0), ATOM_DEVICE_DFP2_SUPPORT); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1806,7 +1811,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1823,12 +1828,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP1_SUPPORT, 0), ATOM_DEVICE_DFP1_SUPPORT); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1842,7 +1847,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1859,7 +1864,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); hpd.hpd = RADEON_HPD_1; /* ??? */ radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP1_SUPPORT, 0), ATOM_DEVICE_DFP1_SUPPORT); @@ -1871,7 +1876,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1883,7 +1888,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1900,7 +1905,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1912,7 +1917,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1924,7 +1929,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c.valid = false; hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_TV1_SUPPORT, 2), ATOM_DEVICE_TV1_SUPPORT); @@ -1941,7 +1946,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -1952,7 +1957,7 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) ddc_i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0); hpd.hpd = RADEON_HPD_NONE; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT2_SUPPORT, 2), ATOM_DEVICE_CRT2_SUPPORT); @@ -1961,6 +1966,48 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) CONNECTOR_OBJECT_ID_VGA, &hpd); break; + case CT_MAC_X800: + DRM_INFO("Connector Table: %d (mac x800)\n", + rdev->mode_info.connector_table); + /* DVI - primary dac, internal tmds */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); + hpd.hpd = RADEON_HPD_1; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP1_SUPPORT, + 0), + ATOM_DEVICE_DFP1_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT1_SUPPORT, + 1), + ATOM_DEVICE_CRT1_SUPPORT); + radeon_add_legacy_connector(dev, 0, + ATOM_DEVICE_DFP1_SUPPORT | + ATOM_DEVICE_CRT1_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, + &hpd); + /* DVI - tv dac, dvo */ + ddc_i2c = combios_setup_i2c_bus(rdev, DDC_MONID, 0, 0); + hpd.hpd = RADEON_HPD_2; /* ??? */ + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_DFP2_SUPPORT, + 0), + ATOM_DEVICE_DFP2_SUPPORT); + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_CRT2_SUPPORT, + 2), + ATOM_DEVICE_CRT2_SUPPORT); + radeon_add_legacy_connector(dev, 1, + ATOM_DEVICE_DFP2_SUPPORT | + ATOM_DEVICE_CRT2_SUPPORT, + DRM_MODE_CONNECTOR_DVII, &ddc_i2c, + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I, + &hpd); + break; default: DRM_INFO("Connector table: %d (invalid)\n", rdev->mode_info.connector_table); @@ -2109,7 +2156,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) else devices = ATOM_DEVICE_DFP1_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, devices, 0), devices); radeon_add_legacy_connector(dev, i, devices, @@ -2123,7 +2170,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) if (tmp & 0x1) { devices = ATOM_DEVICE_CRT2_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_CRT2_SUPPORT, 2), @@ -2131,7 +2178,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) } else { devices = ATOM_DEVICE_CRT1_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_CRT1_SUPPORT, 1), @@ -2151,7 +2198,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) if (tmp & 0x1) { devices |= ATOM_DEVICE_CRT2_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_CRT2_SUPPORT, 2), @@ -2159,7 +2206,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) } else { devices |= ATOM_DEVICE_CRT1_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_CRT1_SUPPORT, 1), @@ -2168,7 +2215,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) if ((tmp >> 4) & 0x1) { devices |= ATOM_DEVICE_DFP2_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_DFP2_SUPPORT, 0), @@ -2177,7 +2224,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) } else { devices |= ATOM_DEVICE_DFP1_SUPPORT; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_DFP1_SUPPORT, 0), @@ -2202,7 +2249,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) connector_object_id = CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I; } radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, devices, 0), devices); radeon_add_legacy_connector(dev, i, devices, @@ -2215,7 +2262,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) case CONNECTOR_CTV_LEGACY: case CONNECTOR_STV_LEGACY: radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_TV1_SUPPORT, 2), @@ -2242,12 +2289,12 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) DRM_DEBUG_KMS("Found DFP table, assuming DVI connector\n"); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_DFP1_SUPPORT, 0), ATOM_DEVICE_DFP1_SUPPORT); @@ -2268,7 +2315,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) DRM_DEBUG_KMS("Found CRT table, assuming VGA connector\n"); if (crt_info) { radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_CRT1_SUPPORT, 1), ATOM_DEVICE_CRT1_SUPPORT); @@ -2297,7 +2344,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) COMBIOS_LCD_DDC_INFO_TABLE); radeon_add_legacy_encoder(dev, - radeon_get_encoder_id(dev, + radeon_get_encoder_enum(dev, ATOM_DEVICE_LCD1_SUPPORT, 0), ATOM_DEVICE_LCD1_SUPPORT); @@ -2351,7 +2398,7 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) hpd.hpd = RADEON_HPD_NONE; ddc_i2c.valid = false; radeon_add_legacy_encoder(dev, - radeon_get_encoder_id + radeon_get_encoder_enum (dev, ATOM_DEVICE_TV1_SUPPORT, 2), diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 47c4b276d30c..ecc1a8fafbfd 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -481,7 +481,8 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector, return MODE_OK; } -static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_lvds_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder = radeon_best_single_encoder(connector); @@ -594,7 +595,8 @@ static int radeon_vga_mode_valid(struct drm_connector *connector, return MODE_OK; } -static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_vga_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder; @@ -691,7 +693,8 @@ static int radeon_tv_mode_valid(struct drm_connector *connector, return MODE_OK; } -static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_tv_detect(struct drm_connector *connector, bool force) { struct drm_encoder *encoder; struct drm_encoder_helper_funcs *encoder_funcs; @@ -748,7 +751,8 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) * we have to check if this analog encoder is shared with anyone else (TV) * if its shared we have to set the other connector to disconnected. */ -static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_dvi_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct drm_encoder *encoder = NULL; @@ -972,32 +976,35 @@ static int radeon_dp_get_modes(struct drm_connector *connector) return ret; } -static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) +static enum drm_connector_status +radeon_dp_detect(struct drm_connector *connector, bool force) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); enum drm_connector_status ret = connector_status_disconnected; struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; - u8 sink_type; if (radeon_connector->edid) { kfree(radeon_connector->edid); radeon_connector->edid = NULL; } - sink_type = radeon_dp_getsinktype(radeon_connector); - if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || - (sink_type == CONNECTOR_OBJECT_ID_eDP)) { - if (radeon_dp_getdpcd(radeon_connector)) { - radeon_dig_connector->dp_sink_type = sink_type; + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + /* eDP is always DP */ + radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; + if (radeon_dp_getdpcd(radeon_connector)) ret = connector_status_connected; - } } else { - if (radeon_ddc_probe(radeon_connector)) { - radeon_dig_connector->dp_sink_type = sink_type; - ret = connector_status_connected; + radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); + if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; + } else { + if (radeon_ddc_probe(radeon_connector)) + ret = connector_status_connected; } } + radeon_connector_update_scratch_regs(connector, ret); return ret; } @@ -1037,7 +1044,6 @@ radeon_add_atom_connector(struct drm_device *dev, uint32_t supported_device, int connector_type, struct radeon_i2c_bus_rec *i2c_bus, - bool linkb, uint32_t igp_lane_info, uint16_t connector_object_id, struct radeon_hpd *hpd, @@ -1050,10 +1056,16 @@ radeon_add_atom_connector(struct drm_device *dev, uint32_t subpixel_order = SubPixelNone; bool shared_ddc = false; - /* fixme - tv/cv/din */ if (connector_type == DRM_MODE_CONNECTOR_Unknown) return; + /* if the user selected tv=0 don't try and add the connector */ + if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || + (connector_type == DRM_MODE_CONNECTOR_Composite) || + (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && + (radeon_tv == 0)) + return; + /* see if we already added it */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { radeon_connector = to_radeon_connector(connector); @@ -1128,7 +1140,6 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); if (!radeon_dig_connector) goto failed; - radeon_dig_connector->linkb = linkb; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); @@ -1158,7 +1169,6 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); if (!radeon_dig_connector) goto failed; - radeon_dig_connector->linkb = linkb; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); @@ -1182,7 +1192,6 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); if (!radeon_dig_connector) goto failed; - radeon_dig_connector->linkb = linkb; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); @@ -1211,25 +1220,22 @@ radeon_add_atom_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: case DRM_MODE_CONNECTOR_9PinDIN: - if (radeon_tv == 1) { - drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); - radeon_connector->dac_load_detect = true; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - 1); - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.tv_std_property, - radeon_atombios_get_tv_info(rdev)); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - } + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + 1); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_atombios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; break; case DRM_MODE_CONNECTOR_LVDS: radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); if (!radeon_dig_connector) goto failed; - radeon_dig_connector->linkb = linkb; radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); @@ -1275,10 +1281,16 @@ radeon_add_legacy_connector(struct drm_device *dev, struct radeon_connector *radeon_connector; uint32_t subpixel_order = SubPixelNone; - /* fixme - tv/cv/din */ if (connector_type == DRM_MODE_CONNECTOR_Unknown) return; + /* if the user selected tv=0 don't try and add the connector */ + if (((connector_type == DRM_MODE_CONNECTOR_SVIDEO) || + (connector_type == DRM_MODE_CONNECTOR_Composite) || + (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) && + (radeon_tv == 0)) + return; + /* see if we already added it */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { radeon_connector = to_radeon_connector(connector); @@ -1350,26 +1362,24 @@ radeon_add_legacy_connector(struct drm_device *dev, case DRM_MODE_CONNECTOR_SVIDEO: case DRM_MODE_CONNECTOR_Composite: case DRM_MODE_CONNECTOR_9PinDIN: - if (radeon_tv == 1) { - drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); - drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); - radeon_connector->dac_load_detect = true; - /* RS400,RC410,RS480 chipset seems to report a lot - * of false positive on load detect, we haven't yet - * found a way to make load detect reliable on those - * chipset, thus just disable it for TV. - */ - if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) - radeon_connector->dac_load_detect = false; - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.load_detect_property, - radeon_connector->dac_load_detect); - drm_connector_attach_property(&radeon_connector->base, - rdev->mode_info.tv_std_property, - radeon_combios_get_tv_info(rdev)); - /* no HPD on analog connectors */ - radeon_connector->hpd.hpd = RADEON_HPD_NONE; - } + drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type); + drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs); + radeon_connector->dac_load_detect = true; + /* RS400,RC410,RS480 chipset seems to report a lot + * of false positive on load detect, we haven't yet + * found a way to make load detect reliable on those + * chipset, thus just disable it for TV. + */ + if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) + radeon_connector->dac_load_detect = false; + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.load_detect_property, + radeon_connector->dac_load_detect); + drm_connector_attach_property(&radeon_connector->base, + rdev->mode_info.tv_std_property, + radeon_combios_get_tv_info(rdev)); + /* no HPD on analog connectors */ + radeon_connector->hpd.hpd = RADEON_HPD_NONE; break; case DRM_MODE_CONNECTOR_LVDS: drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 4f7a170d1566..256d204a6d24 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -199,7 +199,7 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 mc->mc_vram_size = mc->aper_size; } mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; - if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_end <= mc->gtt_end) { + if (rdev->flags & RADEON_IS_AGP && mc->vram_end > mc->gtt_start && mc->vram_start <= mc->gtt_end) { dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n"); mc->real_vram_size = mc->aper_size; mc->mc_vram_size = mc->aper_size; @@ -293,30 +293,20 @@ bool radeon_card_posted(struct radeon_device *rdev) void radeon_update_bandwidth_info(struct radeon_device *rdev) { fixed20_12 a; - u32 sclk, mclk; + u32 sclk = rdev->pm.current_sclk; + u32 mclk = rdev->pm.current_mclk; - if (rdev->flags & RADEON_IS_IGP) { - sclk = radeon_get_engine_clock(rdev); - mclk = rdev->clock.default_mclk; - - a.full = dfixed_const(100); - rdev->pm.sclk.full = dfixed_const(sclk); - rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = dfixed_const(mclk); - rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + /* sclk/mclk in Mhz */ + a.full = dfixed_const(100); + rdev->pm.sclk.full = dfixed_const(sclk); + rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); + rdev->pm.mclk.full = dfixed_const(mclk); + rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); + if (rdev->flags & RADEON_IS_IGP) { a.full = dfixed_const(16); /* core_bandwidth = sclk(Mhz) * 16 */ rdev->pm.core_bandwidth.full = dfixed_div(rdev->pm.sclk, a); - } else { - sclk = radeon_get_engine_clock(rdev); - mclk = radeon_get_memory_clock(rdev); - - a.full = dfixed_const(100); - rdev->pm.sclk.full = dfixed_const(sclk); - rdev->pm.sclk.full = dfixed_div(rdev->pm.sclk, a); - rdev->pm.mclk.full = dfixed_const(mclk); - rdev->pm.mclk.full = dfixed_div(rdev->pm.mclk, a); } } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 5764f4d3b4f1..b92d2f2fcbed 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -349,6 +349,8 @@ static void radeon_print_display_setup(struct drm_device *dev) DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_DFP5_SUPPORT) DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]); + if (devices & ATOM_DEVICE_DFP6_SUPPORT) + DRM_INFO(" DFP6: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_TV1_SUPPORT) DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]); if (devices & ATOM_DEVICE_CV_SUPPORT) @@ -841,8 +843,9 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); - if (radeon_fb->obj) + if (radeon_fb->obj) { drm_gem_object_unreference_unlocked(radeon_fb->obj); + } drm_framebuffer_cleanup(fb); kfree(radeon_fb); } @@ -1094,6 +1097,18 @@ void radeon_modeset_fini(struct radeon_device *rdev) radeon_i2c_fini(rdev); } +static bool is_hdtv_mode(struct drm_display_mode *mode) +{ + /* try and guess if this is a tv or a monitor */ + if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ + (mode->vdisplay == 576) || /* 576p */ + (mode->vdisplay == 720) || /* 720p */ + (mode->vdisplay == 1080)) /* 1080p */ + return true; + else + return false; +} + bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) @@ -1128,20 +1143,22 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, radeon_crtc->rmx_type = radeon_encoder->rmx_type; else radeon_crtc->rmx_type = RMX_OFF; - src_v = crtc->mode.vdisplay; - dst_v = radeon_crtc->native_mode.vdisplay; - src_h = crtc->mode.hdisplay; - dst_h = radeon_crtc->native_mode.vdisplay; /* copy native mode */ memcpy(&radeon_crtc->native_mode, &radeon_encoder->native_mode, sizeof(struct drm_display_mode)); + src_v = crtc->mode.vdisplay; + dst_v = radeon_crtc->native_mode.vdisplay; + src_h = crtc->mode.hdisplay; + dst_h = radeon_crtc->native_mode.hdisplay; /* fix up for overscan on hdmi */ if (ASIC_IS_AVIVO(rdev) && + (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) && ((radeon_encoder->underscan_type == UNDERSCAN_ON) || ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && - drm_detect_hdmi_monitor(radeon_connector->edid)))) { + drm_detect_hdmi_monitor(radeon_connector->edid) && + is_hdtv_mode(mode)))) { radeon_crtc->h_border = (mode->hdisplay >> 5) + 16; radeon_crtc->v_border = (mode->vdisplay >> 5) + 16; radeon_crtc->rmx_type = RMX_FULL; diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 263c8098d7dd..2c293e8304d6 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -81,7 +81,7 @@ void radeon_setup_encoder_clones(struct drm_device *dev) } uint32_t -radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac) +radeon_get_encoder_enum(struct drm_device *dev, uint32_t supported_device, uint8_t dac) { struct radeon_device *rdev = dev->dev_private; uint32_t ret = 0; @@ -97,59 +97,59 @@ radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t if ((rdev->family == CHIP_RS300) || (rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) - ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; + ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; else if (ASIC_IS_AVIVO(rdev)) - ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; + ret = ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1; else - ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; + ret = ENCODER_INTERNAL_DAC1_ENUM_ID1; break; case 2: /* dac b */ if (ASIC_IS_AVIVO(rdev)) - ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; + ret = ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1; else { /*if (rdev->family == CHIP_R200) - ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; else*/ - ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; + ret = ENCODER_INTERNAL_DAC2_ENUM_ID1; } break; case 3: /* external dac */ if (ASIC_IS_AVIVO(rdev)) - ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; + ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; else - ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; break; } break; case ATOM_DEVICE_LCD1_SUPPORT: if (ASIC_IS_AVIVO(rdev)) - ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; + ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; else - ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; + ret = ENCODER_INTERNAL_LVDS_ENUM_ID1; break; case ATOM_DEVICE_DFP1_SUPPORT: if ((rdev->family == CHIP_RS300) || (rdev->family == CHIP_RS400) || (rdev->family == CHIP_RS480)) - ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; else if (ASIC_IS_AVIVO(rdev)) - ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; + ret = ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1; else - ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; + ret = ENCODER_INTERNAL_TMDS1_ENUM_ID1; break; case ATOM_DEVICE_LCD2_SUPPORT: case ATOM_DEVICE_DFP2_SUPPORT: if ((rdev->family == CHIP_RS600) || (rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) - ret = ENCODER_OBJECT_ID_INTERNAL_DDI; + ret = ENCODER_INTERNAL_DDI_ENUM_ID1; else if (ASIC_IS_AVIVO(rdev)) - ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; + ret = ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1; else - ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; + ret = ENCODER_INTERNAL_DVO1_ENUM_ID1; break; case ATOM_DEVICE_DFP3_SUPPORT: - ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; + ret = ENCODER_INTERNAL_LVTM1_ENUM_ID1; break; } @@ -228,32 +228,6 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) return NULL; } -static struct radeon_connector_atom_dig * -radeon_get_atom_connector_priv_from_encoder(struct drm_encoder *encoder) -{ - struct drm_device *dev = encoder->dev; - struct radeon_device *rdev = dev->dev_private; - struct drm_connector *connector; - struct radeon_connector *radeon_connector; - struct radeon_connector_atom_dig *dig_connector; - - if (!rdev->is_atom_bios) - return NULL; - - connector = radeon_get_connector_for_encoder(encoder); - if (!connector) - return NULL; - - radeon_connector = to_radeon_connector(connector); - - if (!radeon_connector->con_priv) - return NULL; - - dig_connector = radeon_connector->con_priv; - - return dig_connector; -} - void radeon_panel_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { @@ -512,14 +486,12 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct radeon_connector_atom_dig *dig_connector = - radeon_get_atom_connector_priv_from_encoder(encoder); union lvds_encoder_control args; int index = 0; int hdmi_detected = 0; uint8_t frev, crev; - if (!dig || !dig_connector) + if (!dig) return; if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) @@ -562,7 +534,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v1.ucMisc |= (1 << 1); } else { - if (dig_connector->linkb) + if (dig->linkb) args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; if (radeon_encoder->pixel_clock > 165000) args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; @@ -601,7 +573,7 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; } } else { - if (dig_connector->linkb) + if (dig->linkb) args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; if (radeon_encoder->pixel_clock > 165000) args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; @@ -623,6 +595,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) int atombios_get_encoder_mode(struct drm_encoder *encoder) { + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; struct drm_connector *connector; struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *dig_connector; @@ -636,9 +610,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ - if (drm_detect_hdmi_monitor(radeon_connector->edid)) - return ATOM_ENCODER_MODE_HDMI; - else if (radeon_connector->use_digital) + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + /* fix me */ + if (ASIC_IS_DCE4(rdev)) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_HDMI; + } else if (radeon_connector->use_digital) return ATOM_ENCODER_MODE_DVI; else return ATOM_ENCODER_MODE_CRT; @@ -646,9 +624,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: default: - if (drm_detect_hdmi_monitor(radeon_connector->edid)) - return ATOM_ENCODER_MODE_HDMI; - else + if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + /* fix me */ + if (ASIC_IS_DCE4(rdev)) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_HDMI; + } else return ATOM_ENCODER_MODE_DVI; break; case DRM_MODE_CONNECTOR_LVDS: @@ -660,9 +642,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return ATOM_ENCODER_MODE_DP; - else if (drm_detect_hdmi_monitor(radeon_connector->edid)) - return ATOM_ENCODER_MODE_HDMI; - else + else if (drm_detect_hdmi_monitor(radeon_connector->edid)) { + /* fix me */ + if (ASIC_IS_DCE4(rdev)) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_HDMI; + } else return ATOM_ENCODER_MODE_DVI; break; case DRM_MODE_CONNECTOR_DVIA: @@ -729,13 +715,24 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct radeon_connector_atom_dig *dig_connector = - radeon_get_atom_connector_priv_from_encoder(encoder); + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); union dig_encoder_control args; int index = 0; uint8_t frev, crev; + int dp_clock = 0; + int dp_lane_count = 0; + + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; - if (!dig || !dig_connector) + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + } + + /* no dig encoder assigned */ + if (dig->dig_encoder == -1) return; memset(&args, 0, sizeof(args)); @@ -757,9 +754,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) args.v1.ucEncoderMode = atombios_get_encoder_mode(encoder); if (args.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) { - if (dig_connector->dp_clock == 270000) + if (dp_clock == 270000) args.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; - args.v1.ucLaneNum = dig_connector->dp_lane_count; + args.v1.ucLaneNum = dp_lane_count; } else if (radeon_encoder->pixel_clock > 165000) args.v1.ucLaneNum = 8; else @@ -781,7 +778,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) args.v1.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; break; } - if (dig_connector->linkb) + if (dig->linkb) args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; else args.v1.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; @@ -804,38 +801,47 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - struct radeon_connector_atom_dig *dig_connector = - radeon_get_atom_connector_priv_from_encoder(encoder); - struct drm_connector *connector; - struct radeon_connector *radeon_connector; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); union dig_transmitter_control args; int index = 0; uint8_t frev, crev; bool is_dp = false; int pll_id = 0; + int dp_clock = 0; + int dp_lane_count = 0; + int connector_object_id = 0; + int igp_lane_info = 0; - if (!dig || !dig_connector) - return; + if (connector) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; - connector = radeon_get_connector_for_encoder(encoder); - radeon_connector = to_radeon_connector(connector); + dp_clock = dig_connector->dp_clock; + dp_lane_count = dig_connector->dp_lane_count; + connector_object_id = + (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; + igp_lane_info = dig_connector->igp_lane_info; + } + + /* no dig encoder assigned */ + if (dig->dig_encoder == -1) + return; if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) is_dp = true; memset(&args, 0, sizeof(args)); - if (ASIC_IS_DCE32(rdev) || ASIC_IS_DCE4(rdev)) + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); - else { - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); - break; - } + break; + case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: + index = GetIndexIntoMasterTable(COMMAND, LVTMATransmitterControl); + break; } if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) @@ -843,14 +849,14 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t args.v1.ucAction = action; if (action == ATOM_TRANSMITTER_ACTION_INIT) { - args.v1.usInitInfo = radeon_connector->connector_object_id; + args.v1.usInitInfo = connector_object_id; } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { args.v1.asMode.ucLaneSel = lane_num; args.v1.asMode.ucLaneSet = lane_set; } else { if (is_dp) args.v1.usPixelClock = - cpu_to_le16(dig_connector->dp_clock / 10); + cpu_to_le16(dp_clock / 10); else if (radeon_encoder->pixel_clock > 165000) args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10); else @@ -858,13 +864,13 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } if (ASIC_IS_DCE4(rdev)) { if (is_dp) - args.v3.ucLaneNum = dig_connector->dp_lane_count; + args.v3.ucLaneNum = dp_lane_count; else if (radeon_encoder->pixel_clock > 165000) args.v3.ucLaneNum = 8; else args.v3.ucLaneNum = 4; - if (dig_connector->linkb) { + if (dig->linkb) { args.v3.acConfig.ucLinkSel = 1; args.v3.acConfig.ucEncoderSel = 1; } @@ -904,7 +910,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t } } else if (ASIC_IS_DCE32(rdev)) { args.v2.acConfig.ucEncoderSel = dig->dig_encoder; - if (dig_connector->linkb) + if (dig->linkb) args.v2.acConfig.ucLinkSel = 1; switch (radeon_encoder->encoder_id) { @@ -938,23 +944,23 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t if ((rdev->flags & RADEON_IS_IGP) && (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) { if (is_dp || (radeon_encoder->pixel_clock <= 165000)) { - if (dig_connector->igp_lane_info & 0x1) + if (igp_lane_info & 0x1) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; - else if (dig_connector->igp_lane_info & 0x2) + else if (igp_lane_info & 0x2) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; - else if (dig_connector->igp_lane_info & 0x4) + else if (igp_lane_info & 0x4) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; - else if (dig_connector->igp_lane_info & 0x8) + else if (igp_lane_info & 0x8) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; } else { - if (dig_connector->igp_lane_info & 0x3) + if (igp_lane_info & 0x3) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; - else if (dig_connector->igp_lane_info & 0xc) + else if (igp_lane_info & 0xc) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; } } - if (dig_connector->linkb) + if (dig->linkb) args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; else args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; @@ -1072,8 +1078,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) if (is_dig) { switch (mode) { case DRM_MODE_DPMS_ON: - if (!ASIC_IS_DCE4(rdev)) - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); @@ -1085,8 +1090,7 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (!ASIC_IS_DCE4(rdev)) - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF); @@ -1290,24 +1294,22 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) uint32_t dig_enc_in_use = 0; if (ASIC_IS_DCE4(rdev)) { - struct radeon_connector_atom_dig *dig_connector = - radeon_get_atom_connector_priv_from_encoder(encoder); - + dig = radeon_encoder->enc_priv; switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - if (dig_connector->linkb) + if (dig->linkb) return 1; else return 0; break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: - if (dig_connector->linkb) + if (dig->linkb) return 3; else return 2; break; case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - if (dig_connector->linkb) + if (dig->linkb) return 5; else return 4; @@ -1641,6 +1643,7 @@ radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder) struct radeon_encoder_atom_dig * radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) { + int encoder_enum = (radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); if (!dig) @@ -1650,11 +1653,16 @@ radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) dig->coherent_mode = true; dig->dig_encoder = -1; + if (encoder_enum == 2) + dig->linkb = true; + else + dig->linkb = false; + return dig; } void -radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) +radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device) { struct radeon_device *rdev = dev->dev_private; struct drm_encoder *encoder; @@ -1663,7 +1671,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su /* see if we already added it */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { radeon_encoder = to_radeon_encoder(encoder); - if (radeon_encoder->encoder_id == encoder_id) { + if (radeon_encoder->encoder_enum == encoder_enum) { radeon_encoder->devices |= supported_device; return; } @@ -1691,7 +1699,8 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su radeon_encoder->enc_priv = NULL; - radeon_encoder->encoder_id = encoder_id; + radeon_encoder->encoder_enum = encoder_enum; + radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; radeon_encoder->devices = supported_device; radeon_encoder->rmx_type = RMX_OFF; radeon_encoder->underscan_type = UNDERSCAN_OFF; diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index dbf86962bdd1..40b0c087b592 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -94,6 +94,7 @@ static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) ret = radeon_bo_reserve(rbo, false); if (likely(ret == 0)) { radeon_bo_kunmap(rbo); + radeon_bo_unpin(rbo); radeon_bo_unreserve(rbo); } drm_gem_object_unreference_unlocked(gobj); @@ -118,7 +119,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, aligned_size = ALIGN(size, PAGE_SIZE); ret = radeon_gem_object_create(rdev, aligned_size, 0, RADEON_GEM_DOMAIN_VRAM, - false, ttm_bo_type_kernel, + false, true, &gobj); if (ret) { printk(KERN_ERR "failed to allocate framebuffer (%d)\n", @@ -325,8 +326,6 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb { struct fb_info *info; struct radeon_framebuffer *rfb = &rfbdev->rfb; - struct radeon_bo *rbo; - int r; if (rfbdev->helper.fbdev) { info = rfbdev->helper.fbdev; @@ -338,14 +337,8 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb } if (rfb->obj) { - rbo = rfb->obj->driver_private; - r = radeon_bo_reserve(rbo, false); - if (likely(r == 0)) { - radeon_bo_kunmap(rbo); - radeon_bo_unpin(rbo); - radeon_bo_unreserve(rbo); - } - drm_gem_object_unreference_unlocked(rfb->obj); + radeonfb_destroy_pinned_object(rfb->obj); + rfb->obj = NULL; } drm_fb_helper_fini(&rfbdev->helper); drm_framebuffer_cleanup(&rfb->base); diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index c578f265b24c..d1e595d91723 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -201,11 +201,11 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data, return r; } r = drm_gem_handle_create(filp, gobj, &handle); + /* drop reference from allocate - handle holds it now */ + drm_gem_object_unreference_unlocked(gobj); if (r) { - drm_gem_object_unreference_unlocked(gobj); return r; } - drm_gem_object_handle_unreference_unlocked(gobj); args->handle = handle; return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index bfd2ce5f5372..6a13ee38a5b9 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -99,6 +99,13 @@ static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state) } } + /* switch the pads to ddc mode */ + if (ASIC_IS_DCE3(rdev) && rec->hw_capable) { + temp = RREG32(rec->mask_clk_reg); + temp &= ~(1 << 16); + WREG32(rec->mask_clk_reg, temp); + } + /* clear the output pin values */ temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask; WREG32(rec->a_clk_reg, temp); @@ -206,7 +213,7 @@ static void post_xfer(struct i2c_adapter *i2c_adap) static u32 radeon_get_i2c_prescale(struct radeon_device *rdev) { - u32 sclk = radeon_get_engine_clock(rdev); + u32 sclk = rdev->pm.current_sclk; u32 prescale = 0; u32 nm; u8 n, m, loop; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 059bfa4098d7..a108c7ed14f5 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -121,11 +121,12 @@ int radeon_irq_kms_init(struct radeon_device *rdev) * chips. Disable MSI on them for now. */ if ((rdev->family >= CHIP_RV380) && - (!(rdev->flags & RADEON_IS_IGP))) { + (!(rdev->flags & RADEON_IS_IGP)) && + (!(rdev->flags & RADEON_IS_AGP))) { int ret = pci_enable_msi(rdev->pdev); if (!ret) { rdev->msi_enabled = 1; - DRM_INFO("radeon: using MSI.\n"); + dev_info(rdev->dev, "radeon: using MSI.\n"); } } rdev->irq.installed = true; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index b1c8ace5f080..8fbbe1c6ebbd 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -161,6 +161,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); return -EINVAL; } + break; case RADEON_INFO_WANT_HYPERZ: /* The "value" here is both an input and output parameter. * If the input value is 1, filp requests hyper-z access. @@ -202,6 +203,10 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) */ int radeon_driver_firstopen_kms(struct drm_device *dev) { + struct radeon_device *rdev = dev->dev_private; + + if (rdev->powered_down) + return -EINVAL; return 0; } @@ -323,45 +328,45 @@ KMS_INVALID_IOCTL(radeon_surface_free_kms) struct drm_ioctl_desc radeon_ioctls_kms[] = { - DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH), /* KMS */ - DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_CS, radeon_cs_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_INFO, radeon_info_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED), }; int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 989df519a1e4..305049afde15 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -272,7 +272,7 @@ static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, if (!ref_div) return 1; - vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div; + vcoFreq = ((unsigned)ref_freq * fb_div) / ref_div; /* * This is horribly crude: the VCO frequency range is divided into diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index b8149cbc0c70..0b8397000f4c 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -1345,7 +1345,7 @@ static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct ra } void -radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) +radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_enum, uint32_t supported_device) { struct radeon_device *rdev = dev->dev_private; struct drm_encoder *encoder; @@ -1354,7 +1354,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t /* see if we already added it */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { radeon_encoder = to_radeon_encoder(encoder); - if (radeon_encoder->encoder_id == encoder_id) { + if (radeon_encoder->encoder_enum == encoder_enum) { radeon_encoder->devices |= supported_device; return; } @@ -1374,7 +1374,8 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t radeon_encoder->enc_priv = NULL; - radeon_encoder->encoder_id = encoder_id; + radeon_encoder->encoder_enum = encoder_enum; + radeon_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; radeon_encoder->devices = supported_device; radeon_encoder->rmx_type = RMX_OFF; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 5bbc086b9267..17a6602b5885 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -204,7 +204,7 @@ struct radeon_i2c_chan { /* mostly for macs, but really any system without connector tables */ enum radeon_connector_table { - CT_NONE, + CT_NONE = 0, CT_GENERIC, CT_IBOOK, CT_POWERBOOK_EXTERNAL, @@ -215,6 +215,7 @@ enum radeon_connector_table { CT_IMAC_G5_ISIGHT, CT_EMAC, CT_RN50_POWER, + CT_MAC_X800, }; enum radeon_dvo_chip { @@ -342,6 +343,7 @@ struct radeon_atom_ss { }; struct radeon_encoder_atom_dig { + bool linkb; /* atom dig */ bool coherent_mode; int dig_encoder; /* -1 disabled, 0 DIGA, 1 DIGB */ @@ -360,6 +362,7 @@ struct radeon_encoder_atom_dac { struct radeon_encoder { struct drm_encoder base; + uint32_t encoder_enum; uint32_t encoder_id; uint32_t devices; uint32_t active_device; @@ -378,7 +381,6 @@ struct radeon_encoder { struct radeon_connector_atom_dig { uint32_t igp_lane_info; - bool linkb; /* displayport */ struct radeon_i2c_chan *dp_i2c_bus; u8 dpcd[8]; @@ -599,7 +601,6 @@ extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct d void radeon_enc_destroy(struct drm_encoder *encoder); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_combios_asic_init(struct drm_device *dev); -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); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 0afd1e62347d..b3b5306bb578 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -69,7 +69,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) u32 c = 0; rbo->placement.fpfn = 0; - rbo->placement.lpfn = 0; + rbo->placement.lpfn = rbo->rdev->mc.active_vram_size >> PAGE_SHIFT; rbo->placement.placement = rbo->placements; rbo->placement.busy_placement = rbo->placements; if (domain & RADEON_GEM_DOMAIN_VRAM) diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 353998dc2c03..3481bc7f6f58 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -124,11 +124,8 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, int r; r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); - if (unlikely(r != 0)) { - if (r != -ERESTARTSYS) - dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo); + if (unlikely(r != 0)) return r; - } spin_lock(&bo->tbo.lock); if (mem_type) *mem_type = bo->tbo.mem.mem_type; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 58038f5cab38..f87efec76236 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -226,6 +226,11 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev) { int i; + /* no need to take locks, etc. if nothing's going to change */ + if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && + (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) + return; + mutex_lock(&rdev->ddev->struct_mutex); mutex_lock(&rdev->vram_mutex); mutex_lock(&rdev->cp.mutex); @@ -632,8 +637,6 @@ void radeon_pm_fini(struct radeon_device *rdev) } radeon_hwmon_fini(rdev); - if (rdev->pm.i2c_bus) - radeon_i2c_destroy(rdev->pm.i2c_bus); } void radeon_pm_compute_clocks(struct radeon_device *rdev) diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index b3ba44c0a818..4ae5a3d1074e 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -3228,34 +3228,34 @@ void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) } struct drm_ioctl_desc radeon_ioctls[] = { - DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH) + DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH) }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index cc05b230d7ef..51d5f7b5ab21 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -693,6 +693,7 @@ void rs600_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); rdev->mc.mc_vram_size = rdev->mc.real_vram_size; rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); base = RREG32_MC(R_000004_MC_FB_LOCATION); base = G_000004_MC_FB_START(base) << 16; diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 3e3f75718be3..4dc2a87ea680 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -157,6 +157,7 @@ void rs690_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index f1c796810117..9490da700749 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -267,6 +267,7 @@ static void rv770_mc_program(struct radeon_device *rdev) */ void r700_cp_stop(struct radeon_device *rdev) { + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT)); } @@ -905,6 +906,54 @@ static void rv770_gpu_init(struct radeon_device *rdev) } +static int rv770_vram_scratch_init(struct radeon_device *rdev) +{ + int r; + u64 gpu_addr; + + if (rdev->vram_scratch.robj == NULL) { + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, + true, RADEON_GEM_DOMAIN_VRAM, + &rdev->vram_scratch.robj); + if (r) { + return r; + } + } + + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->vram_scratch.robj, + RADEON_GEM_DOMAIN_VRAM, &gpu_addr); + if (r) { + radeon_bo_unreserve(rdev->vram_scratch.robj); + return r; + } + r = radeon_bo_kmap(rdev->vram_scratch.robj, + (void **)&rdev->vram_scratch.ptr); + if (r) + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + + return r; +} + +static void rv770_vram_scratch_fini(struct radeon_device *rdev) +{ + int r; + + if (rdev->vram_scratch.robj == NULL) { + return; + } + r = radeon_bo_reserve(rdev->vram_scratch.robj, false); + if (likely(r == 0)) { + radeon_bo_kunmap(rdev->vram_scratch.robj); + radeon_bo_unpin(rdev->vram_scratch.robj); + radeon_bo_unreserve(rdev->vram_scratch.robj); + } + radeon_bo_unref(&rdev->vram_scratch.robj); +} + int rv770_mc_init(struct radeon_device *rdev) { u32 tmp; @@ -944,6 +993,7 @@ int rv770_mc_init(struct radeon_device *rdev) rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; + rdev->mc.active_vram_size = rdev->mc.visible_vram_size; r600_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); @@ -970,6 +1020,9 @@ static int rv770_startup(struct radeon_device *rdev) if (r) return r; } + r = rv770_vram_scratch_init(rdev); + if (r) + return r; rv770_gpu_init(rdev); r = r600_blit_init(rdev); if (r) { @@ -1023,11 +1076,6 @@ int rv770_resume(struct radeon_device *rdev) */ /* post card */ atom_asic_init(rdev->mode_info.atom_context); - /* Initialize clocks */ - r = radeon_clocks_init(rdev); - if (r) { - return r; - } r = rv770_startup(rdev); if (r) { @@ -1118,9 +1166,6 @@ int rv770_init(struct radeon_device *rdev) radeon_surface_init(rdev); /* Initialize clocks */ radeon_get_clock_info(rdev->ddev); - r = radeon_clocks_init(rdev); - if (r) - return r; /* Fence driver */ r = radeon_fence_driver_init(rdev); if (r) @@ -1195,9 +1240,9 @@ void rv770_fini(struct radeon_device *rdev) r600_irq_fini(rdev); radeon_irq_kms_fini(rdev); rv770_pcie_gart_fini(rdev); + rv770_vram_scratch_fini(rdev); radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_clocks_fini(rdev); radeon_agp_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index 976dc8d25280..bf5f83ea14fe 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -1082,10 +1082,10 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) } struct drm_ioctl_desc savage_ioctls[] = { - DRM_IOCTL_DEF(DRM_SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH), - DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH), }; int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls); diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c index 07d0f2979cac..7fe2b63412ce 100644 --- a/drivers/gpu/drm/sis/sis_mm.c +++ b/drivers/gpu/drm/sis/sis_mm.c @@ -320,12 +320,12 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, } struct drm_ioctl_desc sis_ioctls[] = { - DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SIS_FB_FREE, sis_drm_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SIS_AGP_FREE, sis_drm_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), }; int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index cb4cf7ef4d1e..db809e034cc4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -442,6 +442,43 @@ out_err: } /** + * Call bo::reserved and with the lru lock held. + * Will release GPU memory type usage on destruction. + * This is the place to put in driver specific hooks. + * Will release the bo::reserved lock and the + * lru lock on exit. + */ + +static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo) +{ + struct ttm_bo_global *glob = bo->glob; + + if (bo->ttm) { + + /** + * Release the lru_lock, since we don't want to have + * an atomic requirement on ttm_tt[unbind|destroy]. + */ + + spin_unlock(&glob->lru_lock); + ttm_tt_unbind(bo->ttm); + ttm_tt_destroy(bo->ttm); + bo->ttm = NULL; + spin_lock(&glob->lru_lock); + } + + if (bo->mem.mm_node) { + drm_mm_put_block(bo->mem.mm_node); + bo->mem.mm_node = NULL; + } + + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); + spin_unlock(&glob->lru_lock); +} + + +/** * If bo idle, remove from delayed- and lru lists, and unref. * If not idle, and already on delayed list, do nothing. * If not idle, and not on delayed list, put on delayed list, @@ -456,6 +493,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) int ret; spin_lock(&bo->lock); +retry: (void) ttm_bo_wait(bo, false, false, !remove_all); if (!bo->sync_obj) { @@ -464,31 +502,52 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) spin_unlock(&bo->lock); spin_lock(&glob->lru_lock); - put_count = ttm_bo_del_from_lru(bo); + ret = ttm_bo_reserve_locked(bo, false, !remove_all, false, 0); + + /** + * Someone else has the object reserved. Bail and retry. + */ - ret = ttm_bo_reserve_locked(bo, false, false, false, 0); - BUG_ON(ret); - if (bo->ttm) - ttm_tt_unbind(bo->ttm); + if (unlikely(ret == -EBUSY)) { + spin_unlock(&glob->lru_lock); + spin_lock(&bo->lock); + goto requeue; + } + + /** + * We can re-check for sync object without taking + * the bo::lock since setting the sync object requires + * also bo::reserved. A busy object at this point may + * be caused by another thread starting an accelerated + * eviction. + */ + + if (unlikely(bo->sync_obj)) { + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); + spin_unlock(&glob->lru_lock); + spin_lock(&bo->lock); + if (remove_all) + goto retry; + else + goto requeue; + } + + put_count = ttm_bo_del_from_lru(bo); if (!list_empty(&bo->ddestroy)) { list_del_init(&bo->ddestroy); ++put_count; } - if (bo->mem.mm_node) { - drm_mm_put_block(bo->mem.mm_node); - bo->mem.mm_node = NULL; - } - spin_unlock(&glob->lru_lock); - atomic_set(&bo->reserved, 0); + ttm_bo_cleanup_memtype_use(bo); while (put_count--) kref_put(&bo->list_kref, ttm_bo_ref_bug); return 0; } - +requeue: spin_lock(&glob->lru_lock); if (list_empty(&bo->ddestroy)) { void *sync_obj = bo->sync_obj; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 7cffb3e04232..3451a82adba7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -351,6 +351,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, INIT_LIST_HEAD(&fbo->lru); INIT_LIST_HEAD(&fbo->swap); fbo->vm_node = NULL; + atomic_set(&fbo->cpu_writers, 0); fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); kref_init(&fbo->list_kref); diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ca904799f018..b1e02fffd3cc 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -69,7 +69,7 @@ struct ttm_page_pool { spinlock_t lock; bool fill_lock; struct list_head list; - int gfp_flags; + gfp_t gfp_flags; unsigned npages; char *name; unsigned long nfrees; @@ -475,7 +475,7 @@ static void ttm_handle_caching_state_failure(struct list_head *pages, * This function is reentrant if caller updates count depending on number of * pages returned in pages array. */ -static int ttm_alloc_new_pages(struct list_head *pages, int gfp_flags, +static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, int ttm_flags, enum ttm_caching_state cstate, unsigned count) { struct page **caching_array; @@ -666,7 +666,7 @@ int ttm_get_pages(struct list_head *pages, int flags, { struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); struct page *p = NULL; - int gfp_flags = GFP_USER; + gfp_t gfp_flags = GFP_USER; int r; /* set zero flag for page allocation if required */ @@ -818,7 +818,7 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) return 0; } -void ttm_page_alloc_fini() +void ttm_page_alloc_fini(void) { int i; diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c index 68dda74a50ae..cc0ffa9abd00 100644 --- a/drivers/gpu/drm/via/via_dma.c +++ b/drivers/gpu/drm/via/via_dma.c @@ -722,20 +722,20 @@ static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file * } struct drm_ioctl_desc via_ioctls[] = { - DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), - DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), - DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), - DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), - DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) + DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), + DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) }; int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 9dd395b90216..a96ed6d9d010 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -99,47 +99,47 @@ */ #define VMW_IOCTL_DEF(ioctl, func, flags) \ - [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func} + [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_##ioctl, flags, func, DRM_IOCTL_##ioctl} /** * Ioctl definitions. */ static struct drm_ioctl_desc vmw_ioctls[] = { - VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl, + VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl, + VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl, + VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_CURSOR_BYPASS, + VMW_IOCTL_DEF(VMW_CURSOR_BYPASS, vmw_kms_cursor_bypass_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_CONTROL_STREAM, vmw_overlay_ioctl, + VMW_IOCTL_DEF(VMW_CONTROL_STREAM, vmw_overlay_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_CLAIM_STREAM, vmw_stream_claim_ioctl, + VMW_IOCTL_DEF(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_STREAM, vmw_stream_unref_ioctl, + VMW_IOCTL_DEF(VMW_UNREF_STREAM, vmw_stream_unref_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_CONTEXT, vmw_context_define_ioctl, + VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl, + VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_SURFACE, vmw_surface_define_ioctl, + VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl, + VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_REF_SURFACE, vmw_surface_reference_ioctl, + VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_EXECBUF, vmw_execbuf_ioctl, + VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl, + VMW_IOCTL_DEF(VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl, DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl, + VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_wait_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(DRM_IOCTL_VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl, + VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT, vmw_kms_update_layout_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED) }; @@ -148,13 +148,16 @@ static struct pci_device_id vmw_pci_id_list[] = { {0, 0, 0} }; -static char *vmw_devname = "vmwgfx"; +static int enable_fbdev; static int vmw_probe(struct pci_dev *, const struct pci_device_id *); static void vmw_master_init(struct vmw_master *); static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, void *ptr); +MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); +module_param_named(enable_fbdev, enable_fbdev, int, 0600); + static void vmw_print_capabilities(uint32_t capabilities) { DRM_INFO("Capabilities:\n"); @@ -192,8 +195,6 @@ static int vmw_request_device(struct vmw_private *dev_priv) { int ret; - vmw_kms_save_vga(dev_priv); - ret = vmw_fifo_init(dev_priv, &dev_priv->fifo); if (unlikely(ret != 0)) { DRM_ERROR("Unable to initialize FIFO.\n"); @@ -206,9 +207,35 @@ static int vmw_request_device(struct vmw_private *dev_priv) static void vmw_release_device(struct vmw_private *dev_priv) { vmw_fifo_release(dev_priv, &dev_priv->fifo); - vmw_kms_restore_vga(dev_priv); } +int vmw_3d_resource_inc(struct vmw_private *dev_priv) +{ + int ret = 0; + + mutex_lock(&dev_priv->release_mutex); + if (unlikely(dev_priv->num_3d_resources++ == 0)) { + ret = vmw_request_device(dev_priv); + if (unlikely(ret != 0)) + --dev_priv->num_3d_resources; + } + mutex_unlock(&dev_priv->release_mutex); + return ret; +} + + +void vmw_3d_resource_dec(struct vmw_private *dev_priv) +{ + int32_t n3d; + + mutex_lock(&dev_priv->release_mutex); + if (unlikely(--dev_priv->num_3d_resources == 0)) + vmw_release_device(dev_priv); + n3d = (int32_t) dev_priv->num_3d_resources; + mutex_unlock(&dev_priv->release_mutex); + + BUG_ON(n3d < 0); +} static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) { @@ -228,6 +255,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->last_read_sequence = (uint32_t) -100; mutex_init(&dev_priv->hw_mutex); mutex_init(&dev_priv->cmdbuf_mutex); + mutex_init(&dev_priv->release_mutex); rwlock_init(&dev_priv->resource_lock); idr_init(&dev_priv->context_idr); idr_init(&dev_priv->surface_idr); @@ -244,6 +272,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->vram_start = pci_resource_start(dev->pdev, 1); dev_priv->mmio_start = pci_resource_start(dev->pdev, 2); + dev_priv->enable_fb = enable_fbdev; + mutex_lock(&dev_priv->hw_mutex); vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); @@ -343,17 +373,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev->dev_private = dev_priv; - if (!dev->devname) - dev->devname = vmw_devname; - - if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { - ret = drm_irq_install(dev); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed installing irq: %d\n", ret); - goto out_no_irq; - } - } - ret = pci_request_regions(dev->pdev, "vmwgfx probe"); dev_priv->stealth = (ret != 0); if (dev_priv->stealth) { @@ -369,26 +388,52 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) goto out_no_device; } } - ret = vmw_request_device(dev_priv); + ret = vmw_kms_init(dev_priv); if (unlikely(ret != 0)) - goto out_no_device; - vmw_kms_init(dev_priv); + goto out_no_kms; vmw_overlay_init(dev_priv); - vmw_fb_init(dev_priv); + if (dev_priv->enable_fb) { + ret = vmw_3d_resource_inc(dev_priv); + if (unlikely(ret != 0)) + goto out_no_fifo; + vmw_kms_save_vga(dev_priv); + vmw_fb_init(dev_priv); + DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? + "Detected device 3D availability.\n" : + "Detected no device 3D availability.\n"); + } else { + DRM_INFO("Delayed 3D detection since we're not " + "running the device in SVGA mode yet.\n"); + } + + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { + ret = drm_irq_install(dev); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed installing irq: %d\n", ret); + goto out_no_irq; + } + } dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; register_pm_notifier(&dev_priv->pm_nb); - DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n"); - return 0; -out_no_device: - if (dev_priv->capabilities & SVGA_CAP_IRQMASK) - drm_irq_uninstall(dev_priv->dev); - if (dev->devname == vmw_devname) - dev->devname = NULL; out_no_irq: + if (dev_priv->enable_fb) { + vmw_fb_close(dev_priv); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } +out_no_fifo: + vmw_overlay_close(dev_priv); + vmw_kms_close(dev_priv); +out_no_kms: + if (dev_priv->stealth) + pci_release_region(dev->pdev, 2); + else + pci_release_regions(dev->pdev); +out_no_device: ttm_object_device_release(&dev_priv->tdev); out_err4: iounmap(dev_priv->mmio_virt); @@ -415,19 +460,20 @@ static int vmw_driver_unload(struct drm_device *dev) unregister_pm_notifier(&dev_priv->pm_nb); - vmw_fb_close(dev_priv); + if (dev_priv->capabilities & SVGA_CAP_IRQMASK) + drm_irq_uninstall(dev_priv->dev); + if (dev_priv->enable_fb) { + vmw_fb_close(dev_priv); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } vmw_kms_close(dev_priv); vmw_overlay_close(dev_priv); - vmw_release_device(dev_priv); if (dev_priv->stealth) pci_release_region(dev->pdev, 2); else pci_release_regions(dev->pdev); - if (dev_priv->capabilities & SVGA_CAP_IRQMASK) - drm_irq_uninstall(dev_priv->dev); - if (dev->devname == vmw_devname) - dev->devname = NULL; ttm_object_device_release(&dev_priv->tdev); iounmap(dev_priv->mmio_virt); drm_mtrr_del(dev_priv->mmio_mtrr, dev_priv->mmio_start, @@ -500,7 +546,7 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd, struct drm_ioctl_desc *ioctl = &vmw_ioctls[nr - DRM_COMMAND_BASE]; - if (unlikely(ioctl->cmd != cmd)) { + if (unlikely(ioctl->cmd_drv != cmd)) { DRM_ERROR("Invalid command format, ioctl %d\n", nr - DRM_COMMAND_BASE); return -EINVAL; @@ -589,6 +635,16 @@ static int vmw_master_set(struct drm_device *dev, struct vmw_master *vmaster = vmw_master(file_priv->master); int ret = 0; + if (!dev_priv->enable_fb) { + ret = vmw_3d_resource_inc(dev_priv); + if (unlikely(ret != 0)) + return ret; + vmw_kms_save_vga(dev_priv); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_TRACES, 0); + mutex_unlock(&dev_priv->hw_mutex); + } + if (active) { BUG_ON(active != &dev_priv->fbdev_master); ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile); @@ -617,7 +673,13 @@ static int vmw_master_set(struct drm_device *dev, return 0; out_no_active_lock: - vmw_release_device(dev_priv); + if (!dev_priv->enable_fb) { + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_TRACES, 1); + mutex_unlock(&dev_priv->hw_mutex); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } return ret; } @@ -645,11 +707,23 @@ static void vmw_master_drop(struct drm_device *dev, ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); + if (!dev_priv->enable_fb) { + ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM); + if (unlikely(ret != 0)) + DRM_ERROR("Unable to clean VRAM on master drop.\n"); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_TRACES, 1); + mutex_unlock(&dev_priv->hw_mutex); + vmw_kms_restore_vga(dev_priv); + vmw_3d_resource_dec(dev_priv); + } + dev_priv->active_master = &dev_priv->fbdev_master; ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM); ttm_vt_unlock(&dev_priv->fbdev_master.lock); - vmw_fb_on(dev_priv); + if (dev_priv->enable_fb) + vmw_fb_on(dev_priv); } @@ -722,6 +796,7 @@ static struct drm_driver driver = { .irq_postinstall = vmw_irq_postinstall, .irq_uninstall = vmw_irq_uninstall, .irq_handler = vmw_irq_handler, + .get_vblank_counter = vmw_get_vblank_counter, .reclaim_buffers_locked = NULL, .get_map_ofs = drm_core_get_map_ofs, .get_reg_ofs = drm_core_get_reg_ofs, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 429f917b60bf..58de6393f611 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -277,6 +277,7 @@ struct vmw_private { bool stealth; bool is_opened; + bool enable_fb; /** * Master management. @@ -285,6 +286,9 @@ struct vmw_private { struct vmw_master *active_master; struct vmw_master fbdev_master; struct notifier_block pm_nb; + + struct mutex release_mutex; + uint32_t num_3d_resources; }; static inline struct vmw_private *vmw_priv(struct drm_device *dev) @@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv, return val; } +int vmw_3d_resource_inc(struct vmw_private *dev_priv); +void vmw_3d_resource_dec(struct vmw_private *dev_priv); + /** * GMR utilities - vmwgfx_gmr.c */ @@ -511,6 +518,7 @@ void vmw_kms_write_svga(struct vmw_private *vmw_priv, unsigned bbp, unsigned depth); int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); /** * Overlay control - vmwgfx_overlay.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 870967a97c15..409e172f4abf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -615,6 +615,11 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, if (unlikely(ret != 0)) goto err_unlock; + if (bo->mem.mem_type == TTM_PL_VRAM && + bo->mem.mm_node->start < bo->num_pages) + (void) ttm_bo_validate(bo, &vmw_sys_placement, false, + false, false); + ret = ttm_bo_validate(bo, &ne_placement, false, false, false); /* Could probably bug on */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index e6a1eb7ea954..0fe31766e4cf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) mutex_lock(&dev_priv->hw_mutex); dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); + dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); vmw_write(dev_priv, SVGA_REG_ENABLE, 1); min = 4; @@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) dev_priv->config_done_state); vmw_write(dev_priv, SVGA_REG_ENABLE, dev_priv->enable_state); + vmw_write(dev_priv, SVGA_REG_TRACES, + dev_priv->traces_state); mutex_unlock(&dev_priv->hw_mutex); vmw_fence_queue_takedown(&fifo->fence_queue); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 64d7f47df868..e882ba099f0c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv) save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH); save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT); vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID); + if (i == 0 && vmw_priv->num_displays == 1 && + save->width == 0 && save->height == 0) { + + /* + * It should be fairly safe to assume that these + * values are uninitialized. + */ + + save->width = vmw_priv->vga_width - save->pos_x; + save->height = vmw_priv->vga_height - save->pos_y; + } } + return 0; } @@ -984,3 +996,8 @@ out_unlock: ttm_read_unlock(&vmaster->lock); return ret; } + +u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) +{ + return 0; +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 2ff5cf78235f..11cb39e3accb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -27,6 +27,8 @@ #include "vmwgfx_kms.h" +#define VMWGFX_LDU_NUM_DU 8 + #define vmw_crtc_to_ldu(x) \ container_of(x, struct vmw_legacy_display_unit, base.crtc) #define vmw_encoder_to_ldu(x) \ @@ -335,7 +337,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector) } static enum drm_connector_status - vmw_ldu_connector_detect(struct drm_connector *connector) + vmw_ldu_connector_detect(struct drm_connector *connector, + bool force) { if (vmw_connector_to_ldu(connector)->pref_active) return connector_status_connected; @@ -516,7 +519,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - connector->status = vmw_ldu_connector_detect(connector); + connector->status = vmw_ldu_connector_detect(connector, true); drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, DRM_MODE_ENCODER_LVDS); @@ -535,6 +538,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; + int i; + int ret; + if (dev_priv->ldu_priv) { DRM_INFO("ldu system already on\n"); return -EINVAL; @@ -552,23 +559,24 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) drm_mode_create_dirty_info_property(dev_priv->dev); - vmw_ldu_init(dev_priv, 0); - /* for old hardware without multimon only enable one display */ if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { - vmw_ldu_init(dev_priv, 1); - vmw_ldu_init(dev_priv, 2); - vmw_ldu_init(dev_priv, 3); - vmw_ldu_init(dev_priv, 4); - vmw_ldu_init(dev_priv, 5); - vmw_ldu_init(dev_priv, 6); - vmw_ldu_init(dev_priv, 7); + for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i) + vmw_ldu_init(dev_priv, i); + ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU); + } else { + /* for old hardware without multimon only enable one display */ + vmw_ldu_init(dev_priv, 0); + ret = drm_vblank_init(dev, 1); } - return 0; + return ret; } int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv) { + struct drm_device *dev = dev_priv->dev; + + drm_vblank_cleanup(dev); if (!dev_priv->ldu_priv) return -ENOSYS; @@ -610,7 +618,7 @@ int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, ldu->pref_height = 600; ldu->pref_active = false; } - con->status = vmw_ldu_connector_detect(con); + con->status = vmw_ldu_connector_detect(con, true); } mutex_unlock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 5f2d5df01e5c..c8c40e9979db 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res) cmd->body.cid = cpu_to_le32(res->id); vmw_fifo_commit(dev_priv, sizeof(*cmd)); + vmw_3d_resource_dec(dev_priv); } static int vmw_context_init(struct vmw_private *dev_priv, @@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv, cmd->body.cid = cpu_to_le32(res->id); vmw_fifo_commit(dev_priv, sizeof(*cmd)); + (void) vmw_3d_resource_inc(dev_priv); vmw_resource_activate(res, vmw_hw_context_destroy); return 0; } @@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) cmd->body.sid = cpu_to_le32(res->id); vmw_fifo_commit(dev_priv, sizeof(*cmd)); + vmw_3d_resource_dec(dev_priv); } void vmw_surface_res_free(struct vmw_resource *res) @@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv, } vmw_fifo_commit(dev_priv, submit_size); + (void) vmw_3d_resource_inc(dev_priv); vmw_resource_activate(res, vmw_hw_surface_destroy); return 0; } diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c index b87569e96b16..f366f968155a 100644 --- a/drivers/gpu/vga/vgaarb.c +++ b/drivers/gpu/vga/vgaarb.c @@ -598,7 +598,7 @@ static inline void vga_update_device_decodes(struct vga_device *vgadev, pr_debug("vgaarb: decoding count now is: %d\n", vga_decode_count); } -void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace) +static void __vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes, bool userspace) { struct vga_device *vgadev; unsigned long flags; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0c52899be964..3f7292486024 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1285,8 +1285,11 @@ static const struct hid_device_id hid_blacklist[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, @@ -1578,7 +1581,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24) }, { HID_USB_DEVICE(USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1) }, { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT)}, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM)}, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_LCM2)}, { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 85c6d13c9ffa..765a4f53eb5c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -105,6 +105,7 @@ #define USB_VENDOR_ID_ASUS 0x0486 #define USB_DEVICE_ID_ASUS_T91MT 0x0185 +#define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 #define USB_VENDOR_ID_ASUSTEK 0x0b05 #define USB_DEVICE_ID_ASUSTEK_LCM 0x1726 @@ -128,6 +129,7 @@ #define USB_VENDOR_ID_BTC 0x046e #define USB_DEVICE_ID_BTC_EMPREX_REMOTE 0x5578 +#define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2 0x5577 #define USB_VENDOR_ID_CANDO 0x2087 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH 0x0a01 @@ -149,6 +151,7 @@ #define USB_VENDOR_ID_CHICONY 0x04f2 #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 +#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_VENDOR_ID_CIDC 0x1677 @@ -507,6 +510,7 @@ #define USB_VENDOR_ID_UCLOGIC 0x5543 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 +#define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 #define USB_VENDOR_ID_VERNIER 0x08f7 #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c index e91437c18906..ac5421d568f1 100644 --- a/drivers/hid/hid-mosart.c +++ b/drivers/hid/hid-mosart.c @@ -239,6 +239,7 @@ static void mosart_remove(struct hid_device *hdev) static const struct hid_device_id mosart_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { } }; MODULE_DEVICE_TABLE(hid, mosart_devices); diff --git a/drivers/hid/hid-topseed.c b/drivers/hid/hid-topseed.c index 5771f851f856..956ed9ac19d4 100644 --- a/drivers/hid/hid-topseed.c +++ b/drivers/hid/hid-topseed.c @@ -64,6 +64,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id ts_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, { } }; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index b729c0286679..599041a7f670 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -828,6 +828,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co } } else { int skipped_report_id = 0; + int report_id = buf[0]; if (buf[0] == 0x0) { /* Don't send the Report ID */ buf++; @@ -837,7 +838,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), HID_REQ_SET_REPORT, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | *buf, + ((report_type + 1) << 8) | report_id, interface->desc.bInterfaceNumber, buf, count, USB_CTRL_SET_TIMEOUT); /* count also the report id, if this was a numbered report. */ @@ -1445,6 +1446,11 @@ static const struct hid_device_id hid_usb_table[] = { { } }; +struct usb_interface *usbhid_find_interface(int minor) +{ + return usb_find_interface(&hid_driver, minor); +} + static struct hid_driver hid_usb_driver = { .name = "generic-usb", .id_table = hid_usb_table, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2643d3147621..70da3181c8a0 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -33,6 +33,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, @@ -69,6 +70,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, @@ -77,6 +79,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL, HID_QUIRK_HIDINPUT_FORCE }, + { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH, HID_QUIRK_MULTI_INPUT }, + { 0, 0 } }; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 0a29c51114aa..681e620eb95b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -270,7 +270,7 @@ static int hiddev_open(struct inode *inode, struct file *file) struct hiddev *hiddev; int res; - intf = usb_find_interface(&hiddev_driver, iminor(inode)); + intf = usbhid_find_interface(iminor(inode)); if (!intf) return -ENODEV; hid = usb_get_intfdata(intf); diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 693fd3e720df..89d2e847dcc6 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -42,6 +42,7 @@ void usbhid_submit_report (struct hid_device *hid, struct hid_report *report, unsigned char dir); int usbhid_get_power(struct hid_device *hid); void usbhid_put_power(struct hid_device *hid); +struct usb_interface *usbhid_find_interface(int minor); /* iofl flags */ #define HID_CTRL_RUNNING 1 diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 4d4d09bdec0a..97499d00615a 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -409,7 +409,7 @@ config SENSORS_CORETEMP config SENSORS_PKGTEMP tristate "Intel processor package temperature sensor" - depends on X86 && PCI && EXPERIMENTAL + depends on X86 && EXPERIMENTAL help If you say yes here you get support for the package level temperature sensor inside your CPU. Check documentation/driver for details. diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 15c1a9616af3..0683e6be662c 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -79,7 +79,7 @@ struct adm1031_data { int chip_type; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ - unsigned int update_rate; /* In milliseconds */ + unsigned int update_interval; /* In milliseconds */ /* The chan_select_table contains the possible configurations for * auto fan control. */ @@ -743,23 +743,23 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); -/* Update Rate */ -static const unsigned int update_rates[] = { +/* Update Interval */ +static const unsigned int update_intervals[] = { 16000, 8000, 4000, 2000, 1000, 500, 250, 125, }; -static ssize_t show_update_rate(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t show_update_interval(struct device *dev, + struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%u\n", data->update_rate); + return sprintf(buf, "%u\n", data->update_interval); } -static ssize_t set_update_rate(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t set_update_interval(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct adm1031_data *data = i2c_get_clientdata(client); @@ -771,12 +771,15 @@ static ssize_t set_update_rate(struct device *dev, if (err) return err; - /* find the nearest update rate from the table */ - for (i = 0; i < ARRAY_SIZE(update_rates) - 1; i++) { - if (val >= update_rates[i]) + /* + * Find the nearest update interval from the table. + * Use it to determine the matching update rate. + */ + for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { + if (val >= update_intervals[i]) break; } - /* if not found, we point to the last entry (lowest update rate) */ + /* if not found, we point to the last entry (lowest update interval) */ /* set the new update rate while preserving other settings */ reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); @@ -785,14 +788,14 @@ static ssize_t set_update_rate(struct device *dev, adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); mutex_lock(&data->update_lock); - data->update_rate = update_rates[i]; + data->update_interval = update_intervals[i]; mutex_unlock(&data->update_lock); return count; } -static DEVICE_ATTR(update_rate, S_IRUGO | S_IWUSR, show_update_rate, - set_update_rate); +static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, + set_update_interval); static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, @@ -830,7 +833,7 @@ static struct attribute *adm1031_attributes[] = { &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, - &dev_attr_update_rate.attr, + &dev_attr_update_interval.attr, &dev_attr_alarms.attr, NULL @@ -981,7 +984,8 @@ static void adm1031_init_client(struct i2c_client *client) mask = ADM1031_UPDATE_RATE_MASK; read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; - data->update_rate = update_rates[i]; + /* Save it as update interval */ + data->update_interval = update_intervals[i]; } static struct adm1031_data *adm1031_update_device(struct device *dev) @@ -993,7 +997,8 @@ static struct adm1031_data *adm1031_update_device(struct device *dev) mutex_lock(&data->update_lock); - next_update = data->last_updated + msecs_to_jiffies(data->update_rate); + next_update = data->last_updated + + msecs_to_jiffies(data->update_interval); if (time_after(jiffies, next_update) || !data->valid) { dev_dbg(&client->dev, "Starting adm1031 update\n"); diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index b300a2048af1..52319340e182 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -160,30 +160,12 @@ static const struct attribute_group ads7871_group = { static int __devinit ads7871_probe(struct spi_device *spi) { - int status, ret, err = 0; + int ret, err; uint8_t val; struct ads7871_data *pdata; dev_dbg(&spi->dev, "probe\n"); - pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL); - if (!pdata) { - err = -ENOMEM; - goto exit; - } - - status = sysfs_create_group(&spi->dev.kobj, &ads7871_group); - if (status < 0) - goto error_free; - - pdata->hwmon_dev = hwmon_device_register(&spi->dev); - if (IS_ERR(pdata->hwmon_dev)) { - err = PTR_ERR(pdata->hwmon_dev); - goto error_remove; - } - - spi_set_drvdata(spi, pdata); - /* Configure the SPI bus */ spi->mode = (SPI_MODE_0); spi->bits_per_word = 8; @@ -201,6 +183,24 @@ static int __devinit ads7871_probe(struct spi_device *spi) we need to make sure we really have a chip*/ if (val != ret) { err = -ENODEV; + goto exit; + } + + pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL); + if (!pdata) { + err = -ENOMEM; + goto exit; + } + + err = sysfs_create_group(&spi->dev.kobj, &ads7871_group); + if (err < 0) + goto error_free; + + spi_set_drvdata(spi, pdata); + + pdata->hwmon_dev = hwmon_device_register(&spi->dev); + if (IS_ERR(pdata->hwmon_dev)) { + err = PTR_ERR(pdata->hwmon_dev); goto error_remove; } diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index c070c9714cbe..a23b17a78ace 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -36,6 +36,7 @@ #include <linux/pci.h> #include <asm/msr.h> #include <asm/processor.h> +#include <asm/smp.h> #define DRVNAME "coretemp" @@ -423,9 +424,18 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) int err; struct platform_device *pdev; struct pdev_entry *pdev_entry; -#ifdef CONFIG_SMP struct cpuinfo_x86 *c = &cpu_data(cpu); -#endif + + /* + * CPUID.06H.EAX[0] indicates whether the CPU has thermal + * sensors. We check this bit only, all the early CPUs + * without thermal sensors will be filtered out. + */ + if (!cpu_has(c, X86_FEATURE_DTS)) { + printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" + " has no thermal sensor.\n", c->x86_model); + return 0; + } mutex_lock(&pdev_list_mutex); @@ -482,14 +492,22 @@ exit: static void coretemp_device_remove(unsigned int cpu) { - struct pdev_entry *p, *n; + struct pdev_entry *p; + unsigned int i; + mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - if (p->cpu == cpu) { - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } + list_for_each_entry(p, &pdev_list, list) { + if (p->cpu != cpu) + continue; + + platform_device_unregister(p->pdev); + list_del(&p->list); + mutex_unlock(&pdev_list_mutex); + kfree(p); + for_each_cpu(i, cpu_sibling_mask(cpu)) + if (i != cpu && !coretemp_device_add(i)) + break; + return; } mutex_unlock(&pdev_list_mutex); } @@ -518,7 +536,6 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { static int __init coretemp_init(void) { int i, err = -ENODEV; - struct pdev_entry *p, *n; /* quick check if we run Intel */ if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) @@ -528,30 +545,21 @@ static int __init coretemp_init(void) if (err) goto exit; - for_each_online_cpu(i) { - struct cpuinfo_x86 *c = &cpu_data(i); - /* - * CPUID.06H.EAX[0] indicates whether the CPU has thermal - * sensors. We check this bit only, all the early CPUs - * without thermal sensors will be filtered out. - */ - if (c->cpuid_level >= 6 && (cpuid_eax(0x06) & 0x01)) - coretemp_device_add(i); - else { - printk(KERN_INFO DRVNAME ": CPU (model=0x%x)" - " has no thermal sensor.\n", c->x86_model); - } - } + for_each_online_cpu(i) + coretemp_device_add(i); + +#ifndef CONFIG_HOTPLUG_CPU if (list_empty(&pdev_list)) { err = -ENODEV; goto exit_driver_unreg; } +#endif register_hotcpu_notifier(&coretemp_cpu_notifier); return 0; -exit_driver_unreg: #ifndef CONFIG_HOTPLUG_CPU +exit_driver_unreg: platform_driver_unregister(&coretemp_driver); #endif exit: diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 5b58b20dead1..8dee3f38fdfb 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -308,7 +308,6 @@ static int emc1403_probe(struct i2c_client *client, res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr); if (res) { dev_warn(&client->dev, "create group failed\n"); - hwmon_device_unregister(data->hwmon_dev); goto thermal_error1; } data->hwmon_dev = hwmon_device_register(&client->dev); diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 537841ef44b9..75afb3b0e076 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -111,7 +111,7 @@ static struct platform_device *f71882fg_pdev; /* Super-I/O Function prototypes */ static inline int superio_inb(int base, int reg); static inline int superio_inw(int base, int reg); -static inline void superio_enter(int base); +static inline int superio_enter(int base); static inline void superio_select(int base, int ld); static inline void superio_exit(int base); @@ -861,11 +861,20 @@ static int superio_inw(int base, int reg) return val; } -static inline void superio_enter(int base) +static inline int superio_enter(int base) { + /* Don't step on other drivers' I/O space by accident */ + if (!request_muxed_region(base, 2, DRVNAME)) { + printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", + base); + return -EBUSY; + } + /* according to the datasheet the key must be send twice! */ outb(SIO_UNLOCK_KEY, base); outb(SIO_UNLOCK_KEY, base); + + return 0; } static inline void superio_select(int base, int ld) @@ -877,6 +886,7 @@ static inline void superio_select(int base, int ld) static inline void superio_exit(int base) { outb(SIO_LOCK_KEY, base); + release_region(base, 2); } static inline int fan_from_reg(u16 reg) @@ -2175,21 +2185,15 @@ static int f71882fg_remove(struct platform_device *pdev) static int __init f71882fg_find(int sioaddr, unsigned short *address, struct f71882fg_sio_data *sio_data) { - int err = -ENODEV; u16 devid; - - /* Don't step on other drivers' I/O space by accident */ - if (!request_region(sioaddr, 2, DRVNAME)) { - printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", - (int)sioaddr); - return -EBUSY; - } - - superio_enter(sioaddr); + int err = superio_enter(sioaddr); + if (err) + return err; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) { pr_debug(DRVNAME ": Not a Fintek device\n"); + err = -ENODEV; goto exit; } @@ -2213,6 +2217,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, default: printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n", (unsigned int)devid); + err = -ENODEV; goto exit; } @@ -2223,12 +2228,14 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { printk(KERN_WARNING DRVNAME ": Device not activated\n"); + err = -ENODEV; goto exit; } *address = superio_inw(sioaddr, SIO_REG_ADDR); if (*address == 0) { printk(KERN_WARNING DRVNAME ": Base address not set\n"); + err = -ENODEV; goto exit; } *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ @@ -2239,7 +2246,6 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); - release_region(sioaddr, 2); return err; } diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 0f58ecc5334d..9638d58f99fd 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -79,7 +79,7 @@ enum chips { f75373, f75375 }; #define F75375_REG_PWM2_DROP_DUTY 0x6C #define FAN_CTRL_LINEAR(nr) (4 + nr) -#define FAN_CTRL_MODE(nr) (5 + ((nr) * 2)) +#define FAN_CTRL_MODE(nr) (4 + ((nr) * 2)) /* * Data structures and manipulation thereof @@ -298,7 +298,7 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) return -EINVAL; fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); - fanmode = ~(3 << FAN_CTRL_MODE(nr)); + fanmode &= ~(3 << FAN_CTRL_MODE(nr)); switch (val) { case 0: /* Full speed */ @@ -350,7 +350,7 @@ static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); conf = f75375_read8(client, F75375_REG_CONFIG1); - conf = ~(1 << FAN_CTRL_LINEAR(nr)); + conf &= ~(1 << FAN_CTRL_LINEAR(nr)); if (val == 0) conf |= (1 << FAN_CTRL_LINEAR(nr)) ; diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 7580f55e67e3..36e957532230 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -221,6 +221,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left), AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted), AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap), + AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted), + AXIS_DMI_MATCH("Mini5102", "HP Mini 5102", xy_rotated_left_usd), { NULL, } /* Laptop models without axis info (yet): * "NC6910" "HP Compaq 6910" diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index b9bb3e0ca530..39ead2a4d3c5 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -143,6 +143,37 @@ static const struct pci_device_id k8temp_ids[] = { MODULE_DEVICE_TABLE(pci, k8temp_ids); +static int __devinit is_rev_g_desktop(u8 model) +{ + u32 brandidx; + + if (model < 0x69) + return 0; + + if (model == 0xc1 || model == 0x6c || model == 0x7c) + return 0; + + /* + * Differentiate between AM2 and ASB1. + * See "Constructing the processor Name String" in "Revision + * Guide for AMD NPT Family 0Fh Processors" (33610). + */ + brandidx = cpuid_ebx(0x80000001); + brandidx = (brandidx >> 9) & 0x1f; + + /* Single core */ + if ((model == 0x6f || model == 0x7f) && + (brandidx == 0x7 || brandidx == 0x9 || brandidx == 0xc)) + return 0; + + /* Dual core */ + if (model == 0x6b && + (brandidx == 0xb || brandidx == 0xc)) + return 0; + + return 1; +} + static int __devinit k8temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -179,9 +210,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev, "wrong - check erratum #141\n"); } - if ((model >= 0x69) && - !(model == 0xc1 || model == 0x6c || model == 0x7c || - model == 0x6b || model == 0x6f || model == 0x7f)) { + if (is_rev_g_desktop(model)) { /* * RevG desktop CPUs (i.e. no socket S1G1 or * ASB1 parts) need additional offset, diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 6138f036b159..fc591ae53107 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -277,7 +277,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy) wake_up_interruptible(&lis3_dev.misc_wait); kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN); out: - if (lis3_dev.whoami == WAI_8B && lis3_dev.idev && + if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev && lis3_dev.idev->input->users) return IRQ_WAKE_THREAD; return IRQ_HANDLED; @@ -718,7 +718,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) * io-apic is not configurable (and generates a warning) but I keep it * in case of support for other hardware. */ - if (dev->whoami == WAI_8B) + if (dev->pdata && dev->whoami == WAI_8B) thread_fn = lis302dl_interrupt_thread1_8b; else thread_fn = NULL; diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c index dc1f5402c1d7..8e5933b72d19 100644 --- a/drivers/hwmon/lis3lv02d_i2c.c +++ b/drivers/hwmon/lis3lv02d_i2c.c @@ -121,7 +121,7 @@ static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg) { struct lis3lv02d *lis3 = i2c_get_clientdata(client); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweroff(lis3); return 0; } @@ -130,7 +130,7 @@ static int lis3lv02d_i2c_resume(struct i2c_client *client) { struct lis3lv02d *lis3 = i2c_get_clientdata(client); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweron(lis3); return 0; } diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c index 82b16808a274..b9be5e3a22b3 100644 --- a/drivers/hwmon/lis3lv02d_spi.c +++ b/drivers/hwmon/lis3lv02d_spi.c @@ -92,7 +92,7 @@ static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg) { struct lis3lv02d *lis3 = spi_get_drvdata(spi); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweroff(&lis3_dev); return 0; @@ -102,7 +102,7 @@ static int lis3lv02d_spi_resume(struct spi_device *spi) { struct lis3lv02d *lis3 = spi_get_drvdata(spi); - if (!lis3->pdata->wakeup_flags) + if (!lis3->pdata || !lis3->pdata->wakeup_flags) lis3lv02d_poweron(lis3); return 0; diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 94741d42112d..464340f25496 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -91,7 +91,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev); struct lm95241_data { struct device *hwmon_dev; struct mutex update_lock; - unsigned long last_updated, rate; /* in jiffies */ + unsigned long last_updated, interval; /* in jiffies */ char valid; /* zero until following fields are valid */ /* registers values */ u8 local_h, local_l; /* local */ @@ -114,23 +114,23 @@ show_temp(local); show_temp(remote1); show_temp(remote2); -static ssize_t show_rate(struct device *dev, struct device_attribute *attr, +static ssize_t show_interval(struct device *dev, struct device_attribute *attr, char *buf) { struct lm95241_data *data = lm95241_update_device(dev); - snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); + snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval / HZ); return strlen(buf); } -static ssize_t set_rate(struct device *dev, struct device_attribute *attr, +static ssize_t set_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); struct lm95241_data *data = i2c_get_clientdata(client); - strict_strtol(buf, 10, &data->rate); - data->rate = data->rate * HZ / 1000; + strict_strtol(buf, 10, &data->interval); + data->interval = data->interval * HZ / 1000; return count; } @@ -286,7 +286,8 @@ static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); -static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); +static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, + set_interval); static struct attribute *lm95241_attributes[] = { &dev_attr_temp1_input.attr, @@ -298,7 +299,7 @@ static struct attribute *lm95241_attributes[] = { &dev_attr_temp3_min.attr, &dev_attr_temp2_max.attr, &dev_attr_temp3_max.attr, - &dev_attr_rate.attr, + &dev_attr_update_interval.attr, NULL }; @@ -376,7 +377,7 @@ static void lm95241_init_client(struct i2c_client *client) { struct lm95241_data *data = i2c_get_clientdata(client); - data->rate = HZ; /* 1 sec default */ + data->interval = HZ; /* 1 sec default */ data->valid = 0; data->config = CFG_CR0076; data->model = 0; @@ -410,7 +411,7 @@ static struct lm95241_data *lm95241_update_device(struct device *dev) mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + data->rate) || + if (time_after(jiffies, data->last_updated + data->interval) || !data->valid) { dev_dbg(&client->dev, "Updating lm95241 data.\n"); data->local_h = diff --git a/drivers/hwmon/pkgtemp.c b/drivers/hwmon/pkgtemp.c index 74157fcda6ed..f11903936c8b 100644 --- a/drivers/hwmon/pkgtemp.c +++ b/drivers/hwmon/pkgtemp.c @@ -33,7 +33,6 @@ #include <linux/list.h> #include <linux/platform_device.h> #include <linux/cpu.h> -#include <linux/pci.h> #include <asm/msr.h> #include <asm/processor.h> @@ -224,7 +223,7 @@ static int __devinit pkgtemp_probe(struct platform_device *pdev) err = sysfs_create_group(&pdev->dev.kobj, &pkgtemp_group); if (err) - goto exit_free; + goto exit_dev; data->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->hwmon_dev)) { @@ -238,6 +237,8 @@ static int __devinit pkgtemp_probe(struct platform_device *pdev) exit_class: sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group); +exit_dev: + device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); exit_free: kfree(data); exit: @@ -250,6 +251,7 @@ static int __devexit pkgtemp_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &pkgtemp_group); + device_remove_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr); platform_set_drvdata(pdev, NULL); kfree(data); return 0; @@ -281,9 +283,10 @@ static int __cpuinit pkgtemp_device_add(unsigned int cpu) int err; struct platform_device *pdev; struct pdev_entry *pdev_entry; -#ifdef CONFIG_SMP struct cpuinfo_x86 *c = &cpu_data(cpu); -#endif + + if (!cpu_has(c, X86_FEATURE_PTS)) + return 0; mutex_lock(&pdev_list_mutex); @@ -339,17 +342,18 @@ exit: #ifdef CONFIG_HOTPLUG_CPU static void pkgtemp_device_remove(unsigned int cpu) { - struct pdev_entry *p, *n; + struct pdev_entry *p; unsigned int i; int err; mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { + list_for_each_entry(p, &pdev_list, list) { if (p->cpu != cpu) continue; platform_device_unregister(p->pdev); list_del(&p->list); + mutex_unlock(&pdev_list_mutex); kfree(p); for_each_cpu(i, cpu_core_mask(cpu)) { if (i != cpu) { @@ -358,7 +362,7 @@ static void pkgtemp_device_remove(unsigned int cpu) break; } } - break; + return; } mutex_unlock(&pdev_list_mutex); } @@ -399,11 +403,6 @@ static int __init pkgtemp_init(void) goto exit; for_each_online_cpu(i) { - struct cpuinfo_x86 *c = &cpu_data(i); - - if (!cpu_has(c, X86_FEATURE_PTS)) - continue; - err = pkgtemp_device_add(i); if (err) goto exit_devices_unreg; diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index e96e69dd36fb..072c58008a63 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -127,6 +127,7 @@ superio_enter(int ioreg) static inline void superio_exit(int ioreg) { + outb(0xaa, ioreg); outb(0x02, ioreg); outb(0x02, ioreg + 1); } diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index f7bd2613cecc..f2de3be35df3 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -677,6 +677,11 @@ static int __devinit cpm_i2c_probe(struct platform_device *ofdev, dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", cpm->adap.name); + /* + * register OF I2C devices + */ + of_i2c_register_devices(&cpm->adap); + return 0; out_shut: cpm_i2c_shutdown(cpm); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 2222c87876b9..b8feac5f2ef4 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -357,9 +357,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->terminate = 0; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - /* * First byte should be set here, not after interrupt, * because transmit-data-ready interrupt can come before @@ -371,6 +368,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->buf_len--; } + /* write the data into mode register; start transmitting */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, dev->adapter.timeout); if (r == 0) { diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index 43ca32fddde2..89eedf45d30e 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -761,6 +761,9 @@ static int __devinit iic_probe(struct platform_device *ofdev, dev_info(&ofdev->dev, "using %s mode\n", dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); + /* Now register all the child nodes */ + of_i2c_register_devices(adap); + return 0; error_cleanup: diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index a1c419a716af..b74e6dc6886c 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -632,6 +632,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op, dev_err(i2c->dev, "failed to add adapter\n"); goto fail_add; } + of_i2c_register_devices(&i2c->adap); return result; diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 0e9f85d0a835..56dbe54e8811 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -218,7 +218,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c) return result; } else if (result == 0) { dev_dbg(i2c->dev, "%s: timeout\n", __func__); - result = -ETIMEDOUT; + return -ETIMEDOUT; } return 0; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 7674efb55378..b33c78586bfc 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -680,6 +680,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r == 0) r = num; + + omap_i2c_wait_for_bb(dev); out: omap_i2c_idle(dev); return r; diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index bbd77603a417..29933f87d8fa 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -71,8 +71,8 @@ static int pca_isa_readbyte(void *pd, int reg) static int pca_isa_waitforcompletion(void *pd) { - long ret = ~0; unsigned long timeout; + long ret; if (irq > -1) { ret = wait_event_timeout(pca_wait, @@ -81,11 +81,15 @@ static int pca_isa_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + pca_isa_ops.timeout; - while (((pca_isa_readbyte(pd, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (pca_isa_readbyte(pd, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } + return ret > 0; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index ef5c78487eb7..5f6d7f89e225 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -80,8 +80,8 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) static int i2c_pca_pf_waitforcompletion(void *pd) { struct i2c_pca_pf_data *i2c = pd; - long ret = ~0; unsigned long timeout; + long ret; if (i2c->irq) { ret = wait_event_timeout(i2c->wait, @@ -90,10 +90,13 @@ static int i2c_pca_pf_waitforcompletion(void *pd) } else { /* Do polling */ timeout = jiffies + i2c->adap.timeout; - while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI) == 0) - && (ret = time_before(jiffies, timeout))) + do { + ret = time_before(jiffies, timeout); + if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON) + & I2C_PCA_CON_SI) + break; udelay(100); + } while (ret); } return ret > 0; diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 72902e0bbfa7..bf831bf81587 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -662,8 +662,8 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) unsigned long sda_delay; if (pdata->sda_delay) { - sda_delay = (freq / 1000) * pdata->sda_delay; - sda_delay /= 1000000; + sda_delay = clkin * pdata->sda_delay; + sda_delay = DIV_ROUND_UP(sda_delay, 1000000); sda_delay = DIV_ROUND_UP(sda_delay, 5); if (sda_delay > 3) sda_delay = 3; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 6649176de940..bea4c5021d26 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -32,7 +32,6 @@ #include <linux/init.h> #include <linux/idr.h> #include <linux/mutex.h> -#include <linux/of_i2c.h> #include <linux/of_device.h> #include <linux/completion.h> #include <linux/hardirq.h> @@ -197,11 +196,12 @@ static int i2c_device_pm_suspend(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->suspend ? pm->suspend(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->suspend ? pm->suspend(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_SUSPEND); } @@ -216,12 +216,6 @@ static int i2c_device_pm_resume(struct device *dev) else ret = i2c_legacy_resume(dev); - if (!ret) { - pm_runtime_disable(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - } - return ret; } @@ -229,11 +223,12 @@ static int i2c_device_pm_freeze(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->freeze ? pm->freeze(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->freeze ? pm->freeze(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_FREEZE); } @@ -242,11 +237,12 @@ static int i2c_device_pm_thaw(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->thaw ? pm->thaw(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->thaw ? pm->thaw(dev) : 0; + } return i2c_legacy_resume(dev); } @@ -255,11 +251,12 @@ static int i2c_device_pm_poweroff(struct device *dev) { const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - if (pm_runtime_suspended(dev)) - return 0; - - if (pm) - return pm->poweroff ? pm->poweroff(dev) : 0; + if (pm) { + if (pm_runtime_suspended(dev)) + return 0; + else + return pm->poweroff ? pm->poweroff(dev) : 0; + } return i2c_legacy_suspend(dev, PMSG_HIBERNATE); } @@ -876,9 +873,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); - /* Register devices from the device tree */ - of_i2c_register_devices(adap); - /* Notify drivers */ mutex_lock(&core_lock); bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 4c3d1bfec0c5..068cef0a987a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1448,19 +1448,13 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif == NULL) continue; - if (hwif->present) - hwif_register_devices(hwif); - } - - ide_host_for_each_port(i, hwif, host) { - if (hwif == NULL) - continue; - ide_sysfs_register_port(hwif); ide_proc_register_port(hwif); - if (hwif->present) + if (hwif->present) { ide_proc_port_register_devices(hwif); + hwif_register_devices(hwif); + } } return j ? 0 : -1; diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index a10152bb1427..c37ef64d1465 100755..100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -83,7 +83,7 @@ static unsigned int mwait_substates; /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ static unsigned int lapic_timer_reliable_states; -static struct cpuidle_device *intel_idle_cpuidle_devices; +static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); static struct cpuidle_state *cpuidle_state_table; @@ -108,7 +108,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { .name = "NHM-C3", .desc = "MWAIT 0x10", .driver_data = (void *) 0x10, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 20, .power_usage = 500, .target_residency = 80, @@ -117,7 +117,7 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { .name = "NHM-C6", .desc = "MWAIT 0x20", .driver_data = (void *) 0x20, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 200, .power_usage = 350, .target_residency = 800, @@ -149,7 +149,7 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { .name = "ATM-C4", .desc = "MWAIT 0x30", .driver_data = (void *) 0x30, - .flags = CPUIDLE_FLAG_TIME_VALID, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, .exit_latency = 100, .power_usage = 250, .target_residency = 400, @@ -157,13 +157,13 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C5 */ }, { /* MWAIT C6 */ .name = "ATM-C6", - .desc = "MWAIT 0x40", - .driver_data = (void *) 0x40, - .flags = CPUIDLE_FLAG_TIME_VALID, - .exit_latency = 200, + .desc = "MWAIT 0x52", + .driver_data = (void *) 0x52, + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 140, .power_usage = 150, - .target_residency = 800, - .enter = NULL }, /* disabled */ + .target_residency = 560, + .enter = &intel_idle }, }; /** @@ -185,6 +185,16 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) local_irq_disable(); + /* + * If the state flag indicates that the TLB will be flushed or if this + * is the deepest c-state supported, do a voluntary leave mm to avoid + * costly and mostly unnecessary wakeups for flushing the user TLB's + * associated with the active mm. + */ + if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED || + (&dev->states[dev->state_count - 1] == state)) + leave_mm(cpu); + if (!(lapic_timer_reliable_states & (1 << (cstate)))) clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index d0dc1db80b29..50815022cff1 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -1106,7 +1106,7 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso) if (recv->block_irq_interval * 4 > iso->buf_packets) recv->block_irq_interval = iso->buf_packets / 4; if (recv->block_irq_interval < 1) - recv->block_irq_interval = 1; + recv->block_irq_interval = 1; /* choose a buffer stride */ /* must be a power of 2, and <= PAGE_SIZE */ diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index 8f0caf7d4482..78fbe9ffe7f0 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h @@ -53,7 +53,7 @@ #define T3_MAX_PBL_SIZE 256 #define T3_MAX_RQ_SIZE 1024 #define T3_MAX_QP_DEPTH (T3_MAX_RQ_SIZE-1) -#define T3_MAX_CQ_DEPTH 262144 +#define T3_MAX_CQ_DEPTH 65536 #define T3_MAX_NUM_STAG (1<<15) #define T3_MAX_MR_SIZE 0x100000000ULL #define T3_PAGESIZE_MASK 0xffff000 /* 4KB-128MB */ diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c index d88077a21994..13c88871dc3b 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -463,7 +463,8 @@ static int send_connect(struct iwch_ep *ep) V_MSS_IDX(mtu_idx) | V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx); opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10); - opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor); + opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) | + V_CONG_CONTROL_FLAVOR(cong_flavor); skb->priority = CPL_PRIORITY_SETUP; set_arp_failure_handler(skb, act_open_req_arp_failure); @@ -1280,7 +1281,8 @@ static void accept_cr(struct iwch_ep *ep, __be32 peer_ip, struct sk_buff *skb) V_MSS_IDX(mtu_idx) | V_L2T_IDX(ep->l2t->idx) | V_TX_CHANNEL(ep->l2t->smt_idx); opt0l = V_TOS((ep->tos >> 2) & M_TOS) | V_RCV_BUFSIZ(rcv_win>>10); - opt2 = V_FLAVORS_VALID(1) | V_CONG_CONTROL_FLAVOR(cong_flavor); + opt2 = F_RX_COALESCE_VALID | V_RX_COALESCE(0) | V_FLAVORS_VALID(1) | + V_CONG_CONTROL_FLAVOR(cong_flavor); rpl = cplhdr(skb); rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 443cea55daac..61e0efd4ccfb 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -502,7 +502,9 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb, static void nes_retrans_expired(struct nes_cm_node *cm_node) { struct iw_cm_id *cm_id = cm_node->cm_id; - switch (cm_node->state) { + enum nes_cm_node_state state = cm_node->state; + cm_node->state = NES_CM_STATE_CLOSED; + switch (state) { case NES_CM_STATE_SYN_RCVD: case NES_CM_STATE_CLOSING: rem_ref_cm_node(cm_node->cm_core, cm_node); @@ -511,7 +513,6 @@ static void nes_retrans_expired(struct nes_cm_node *cm_node) case NES_CM_STATE_FIN_WAIT1: if (cm_node->cm_id) cm_id->rem_ref(cm_id); - cm_node->state = NES_CM_STATE_CLOSED; send_reset(cm_node, NULL); break; default: @@ -1439,9 +1440,6 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, break; case NES_CM_STATE_MPAREQ_RCVD: passive_state = atomic_add_return(1, &cm_node->passive_state); - if (passive_state == NES_SEND_RESET_EVENT) - create_event(cm_node, NES_CM_EVENT_RESET); - cm_node->state = NES_CM_STATE_CLOSED; dev_kfree_skb_any(skb); break; case NES_CM_STATE_ESTABLISHED: @@ -1456,6 +1454,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb, case NES_CM_STATE_CLOSED: drop_packet(skb); break; + case NES_CM_STATE_FIN_WAIT2: case NES_CM_STATE_FIN_WAIT1: case NES_CM_STATE_LAST_ACK: cm_node->cm_id->rem_ref(cm_node->cm_id); @@ -2777,6 +2776,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) return -EINVAL; } + passive_state = atomic_add_return(1, &cm_node->passive_state); + if (passive_state == NES_SEND_RESET_EVENT) { + rem_ref_cm_node(cm_node->cm_core, cm_node); + return -ECONNRESET; + } + /* associate the node with the QP */ nesqp->cm_node = (void *)cm_node; cm_node->nesqp = nesqp; @@ -2979,9 +2984,6 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) printk(KERN_ERR "%s[%u] OFA CM event_handler returned, " "ret=%d\n", __func__, __LINE__, ret); - passive_state = atomic_add_return(1, &cm_node->passive_state); - if (passive_state == NES_SEND_RESET_EVENT) - create_event(cm_node, NES_CM_EVENT_RESET); return 0; } diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index f8233c851c69..1980a461c499 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -3468,6 +3468,19 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, return; /* Ignore it, wait for close complete */ if (atomic_inc_return(&nesqp->close_timer_started) == 1) { + if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) && + (nesqp->ibqp_state == IB_QPS_RTS) && + ((nesadapter->eeprom_version >> 16) != NES_A0)) { + spin_lock_irqsave(&nesqp->lock, flags); + nesqp->hw_iwarp_state = iwarp_state; + nesqp->hw_tcp_state = tcp_state; + nesqp->last_aeq = async_event_id; + next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING; + nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING; + spin_unlock_irqrestore(&nesqp->lock, flags); + nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0, 0); + nes_cm_disconn(nesqp); + } nesqp->cm_id->add_ref(nesqp->cm_id); schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp, NES_TIMER_TYPE_CLOSE, 1, 0); @@ -3477,7 +3490,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount), async_event_id, nesqp->last_aeq, tcp_state); } - break; case NES_AEQE_AEID_LLP_CLOSE_COMPLETE: if (nesqp->term_flags) { diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index aa9183db32b1..1204c3432b63 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -45,6 +45,7 @@ #define NES_PHY_TYPE_KR 9 #define NES_MULTICAST_PF_MAX 8 +#define NES_A0 3 enum pci_regs { NES_INT_STAT = 0x0000, diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 6dfdd49cdbcf..10560c796fd6 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1446,14 +1446,14 @@ static int nes_netdev_set_pauseparam(struct net_device *netdev, NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200)); u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE; nes_write_indexed(nesdev, - NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp); + NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200), u32temp); nesdev->disable_tx_flow_control = 0; } else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) { u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200)); u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE; nes_write_indexed(nesdev, - NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp); + NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200), u32temp); nesdev->disable_tx_flow_control = 1; } if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) { diff --git a/drivers/input/input.c b/drivers/input/input.c index a9b025f4147a..ab6982056518 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1599,11 +1599,14 @@ EXPORT_SYMBOL(input_free_device); * @dev: input device supporting MT events and finger tracking * @num_slots: number of slots used by the device * - * This function allocates all necessary memory for MT slot handling - * in the input device, and adds ABS_MT_SLOT to the device capabilities. + * This function allocates all necessary memory for MT slot handling in the + * input device, and adds ABS_MT_SLOT to the device capabilities. All slots + * are initially marked as unused iby setting ABS_MT_TRACKING_ID to -1. */ int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) { + int i; + if (!num_slots) return 0; @@ -1614,6 +1617,10 @@ int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) dev->mtsize = num_slots; input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); + /* Mark slots as 'unused' */ + for (i = 0; i < num_slots; i++) + dev->mt[i].abs[ABS_MT_TRACKING_ID - ABS_MT_FIRST] = -1; + return 0; } EXPORT_SYMBOL(input_mt_create_slots); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index d85bd8a7967d..22239e988498 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -483,6 +483,9 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, memcpy(joydev->abspam, abspam, len); + for (i = 0; i < joydev->nabs; i++) + joydev->absmap[joydev->abspam[i]] = i; + out: kfree(abspam); return retval; diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index dcc86b97a153..19fa94af207a 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -232,13 +232,13 @@ static void hil_dev_handle_ptr_events(struct hil_dev *ptr) if (absdev) { val = lo + (hi << 8); #ifdef TABLET_AUTOADJUST - if (val < input_abs_min(dev, ABS_X + i)) + if (val < input_abs_get_min(dev, ABS_X + i)) input_abs_set_min(dev, ABS_X + i, val); - if (val > input_abs_max(dev, ABS_X + i)) + if (val > input_abs_get_max(dev, ABS_X + i)) input_abs_set_max(dev, ABS_X + i, val); #endif if (i % 3) - val = input_abs_max(dev, ABS_X + i) - val; + val = input_abs_get_max(dev, ABS_X + i) - val; input_report_abs(dev, ABS_X + i, val); } else { val = (int) (((int8_t) lo) | ((int8_t) hi << 8)); @@ -388,11 +388,11 @@ static void hil_dev_pointer_setup(struct hil_dev *ptr) #ifdef TABLET_AUTOADJUST for (i = 0; i < ABS_MAX; i++) { - int diff = input_abs_max(input_dev, ABS_X + i) / 10; + int diff = input_abs_get_max(input_dev, ABS_X + i) / 10; input_abs_set_min(input_dev, ABS_X + i, - input_abs_min(input_dev, ABS_X + i) + diff) + input_abs_get_min(input_dev, ABS_X + i) + diff); input_abs_set_max(input_dev, ABS_X + i, - input_abs_max(input_dev, ABS_X + i) - diff) + input_abs_get_max(input_dev, ABS_X + i) - diff); } #endif diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 0e53b3bc39af..f32404f99189 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -567,8 +567,6 @@ static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) clk_put(keypad->clk); input_unregister_device(keypad->input_dev); - input_free_device(keypad->input_dev); - iounmap(keypad->mmio_base); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index bb53fd33cd1c..360698553eb5 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -404,6 +404,13 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu retval = uinput_validate_absbits(dev); if (retval < 0) goto exit; + if (test_bit(ABS_MT_SLOT, dev->absbit)) { + int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1; + input_mt_create_slots(dev, nslot); + input_set_events_per_packet(dev, 6 * nslot); + } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { + input_set_events_per_packet(dev, 60); + } } udev->state = UIST_SETUP_COMPLETE; @@ -811,6 +818,8 @@ static struct miscdevice uinput_misc = { .minor = UINPUT_MINOR, .name = UINPUT_NAME, }; +MODULE_ALIAS_MISCDEV(UINPUT_MINOR); +MODULE_ALIAS("devname:" UINPUT_NAME); static int __init uinput_init(void) { diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index ea67c49146a3..b95231763911 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -337,10 +337,14 @@ static void report_finger_data(struct input_dev *input, const struct bcm5974_config *cfg, const struct tp_finger *f) { - input_report_abs(input, ABS_MT_TOUCH_MAJOR, raw2int(f->force_major)); - input_report_abs(input, ABS_MT_TOUCH_MINOR, raw2int(f->force_minor)); - input_report_abs(input, ABS_MT_WIDTH_MAJOR, raw2int(f->size_major)); - input_report_abs(input, ABS_MT_WIDTH_MINOR, raw2int(f->size_minor)); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, + raw2int(f->force_major) << 1); + input_report_abs(input, ABS_MT_TOUCH_MINOR, + raw2int(f->force_minor) << 1); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, + raw2int(f->size_major) << 1); + input_report_abs(input, ABS_MT_WIDTH_MINOR, + raw2int(f->size_minor) << 1); input_report_abs(input, ABS_MT_ORIENTATION, MAX_FINGER_ORIENTATION - raw2int(f->orientation)); input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 83c24cca234a..d528a2dba064 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -138,8 +138,8 @@ static void mousedev_touchpad_event(struct input_dev *dev, fx(0) = value; if (mousedev->touch && mousedev->pkt_count >= 2) { - size = input_abs_get_min(dev, ABS_X) - - input_abs_get_max(dev, ABS_X); + size = input_abs_get_max(dev, ABS_X) - + input_abs_get_min(dev, ABS_X); if (size == 0) size = 256 * 2; @@ -155,8 +155,8 @@ static void mousedev_touchpad_event(struct input_dev *dev, fy(0) = value; if (mousedev->touch && mousedev->pkt_count >= 2) { /* use X size for ABS_Y to keep the same scale */ - size = input_abs_get_min(dev, ABS_X) - - input_abs_get_max(dev, ABS_X); + size = input_abs_get_max(dev, ABS_X) - + input_abs_get_min(dev, ABS_X); if (size == 0) size = 256 * 2; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 46e4ba0b9246..f58513160480 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1485,8 +1485,8 @@ static int __init i8042_init(void) static void __exit i8042_exit(void) { - platform_driver_unregister(&i8042_driver); platform_device_unregister(i8042_platform_device); + platform_driver_unregister(&i8042_driver); i8042_platform_exit(); panic_blink = NULL; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 42ba3691d908..b35876ee6908 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -103,27 +103,26 @@ static void wacom_sys_irq(struct urb *urb) static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); + int retval = 0; - mutex_lock(&wacom->lock); - - wacom->irq->dev = wacom->usbdev; - - if (usb_autopm_get_interface(wacom->intf) < 0) { - mutex_unlock(&wacom->lock); + if (usb_autopm_get_interface(wacom->intf) < 0) return -EIO; - } + + mutex_lock(&wacom->lock); if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { - usb_autopm_put_interface(wacom->intf); - mutex_unlock(&wacom->lock); - return -EIO; + retval = -EIO; + goto out; } wacom->open = true; wacom->intf->needs_remote_wakeup = 1; +out: mutex_unlock(&wacom->lock); - return 0; + if (retval) + usb_autopm_put_interface(wacom->intf); + return retval; } static void wacom_close(struct input_dev *dev) @@ -135,6 +134,8 @@ static void wacom_close(struct input_dev *dev) wacom->open = false; wacom->intf->needs_remote_wakeup = 0; mutex_unlock(&wacom->lock); + + usb_autopm_put_interface(wacom->intf); } static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 40d77ba8fdc1..47fd7a041c52 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -243,10 +243,10 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) if (features->type == WACOM_G4 || features->type == WACOM_MO) { input_report_abs(input, ABS_DISTANCE, data[6] & 0x3f); - rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); + rw = (data[7] & 0x04) - (data[7] & 0x03); } else { input_report_abs(input, ABS_DISTANCE, data[7] & 0x3f); - rw = -(signed)data[6]; + rw = -(signed char)data[6]; } input_report_rel(input, REL_WHEEL, rw); } @@ -442,8 +442,10 @@ static void wacom_intuos_general(struct wacom_wac *wacom) /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (features->type >= INTUOS4S && features->type <= INTUOS4L) + if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || + features->type == WACOM_21UX2) { t = (t << 1) | (data[1] & 1); + } input_report_abs(input, ABS_PRESSURE, t); input_report_abs(input, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); diff --git a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig index 5dbcbe3a54a6..b99b906ea9b1 100644 --- a/drivers/isdn/hardware/avm/Kconfig +++ b/drivers/isdn/hardware/avm/Kconfig @@ -36,12 +36,13 @@ config ISDN_DRV_AVMB1_T1ISA config ISDN_DRV_AVMB1_B1PCMCIA tristate "AVM B1/M1/M2 PCMCIA support" + depends on PCMCIA help Enable support for the PCMCIA version of the AVM B1 card. config ISDN_DRV_AVMB1_AVM_CS tristate "AVM B1/M1/M2 PCMCIA cs module" - depends on ISDN_DRV_AVMB1_B1PCMCIA && PCMCIA + depends on ISDN_DRV_AVMB1_B1PCMCIA help Enable the PCMCIA client driver for the AVM B1/M1/M2 PCMCIA cards. diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c index 485be8b1e1b3..f0225bc0f267 100644 --- a/drivers/isdn/sc/interrupt.c +++ b/drivers/isdn/sc/interrupt.c @@ -112,11 +112,19 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) } else if(callid>=0x0000 && callid<=0x7FFF) { + int len; + pr_debug("%s: Got Incoming Call\n", sc_adapter[card]->devicename); - strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4])); - strcpy(setup.eazmsn, - sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn); + len = strlcpy(setup.phone, &(rcvmsg.msg_data.byte_array[4]), + sizeof(setup.phone)); + if (len >= sizeof(setup.phone)) + continue; + len = strlcpy(setup.eazmsn, + sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, + sizeof(setup.eazmsn)); + if (len >= sizeof(setup.eazmsn)) + continue; setup.si1 = 7; setup.si2 = 0; setup.plan = 0; @@ -176,7 +184,9 @@ irqreturn_t interrupt_handler(int dummy, void *card_inst) * Handle a GetMyNumber Rsp */ if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ - strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); + strlcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no - 1].dn, + rcvmsg.msg_data.byte_array, + sizeof(rcvmsg.msg_data.byte_array)); continue; } diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c index 74dce4ba0262..350eb34f049c 100644 --- a/drivers/leds/leds-ns2.c +++ b/drivers/leds/leds-ns2.c @@ -81,7 +81,7 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat, int cmd_level; int slow_level; - read_lock(&led_dat->rw_lock); + read_lock_irq(&led_dat->rw_lock); cmd_level = gpio_get_value(led_dat->cmd); slow_level = gpio_get_value(led_dat->slow); @@ -95,7 +95,7 @@ static int ns2_led_get_mode(struct ns2_led_data *led_dat, } } - read_unlock(&led_dat->rw_lock); + read_unlock_irq(&led_dat->rw_lock); return ret; } @@ -104,8 +104,9 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat, enum ns2_led_modes mode) { int i; + unsigned long flags; - write_lock(&led_dat->rw_lock); + write_lock_irqsave(&led_dat->rw_lock, flags); for (i = 0; i < ARRAY_SIZE(ns2_led_modval); i++) { if (mode == ns2_led_modval[i].mode) { @@ -116,7 +117,7 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat, } } - write_unlock(&led_dat->rw_lock); + write_unlock_irqrestore(&led_dat->rw_lock, flags); } static void ns2_led_set(struct led_classdev *led_cdev, diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 35bc2737412f..2d17e76066bd 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -45,6 +45,7 @@ #include <linux/syscalls.h> #include <linux/suspend.h> #include <linux/cpu.h> +#include <linux/compat.h> #include <asm/prom.h> #include <asm/machdep.h> #include <asm/io.h> @@ -2349,11 +2350,52 @@ static long pmu_unlocked_ioctl(struct file *filp, return ret; } +#ifdef CONFIG_COMPAT +#define PMU_IOC_GET_BACKLIGHT32 _IOR('B', 1, compat_size_t) +#define PMU_IOC_SET_BACKLIGHT32 _IOW('B', 2, compat_size_t) +#define PMU_IOC_GET_MODEL32 _IOR('B', 3, compat_size_t) +#define PMU_IOC_HAS_ADB32 _IOR('B', 4, compat_size_t) +#define PMU_IOC_CAN_SLEEP32 _IOR('B', 5, compat_size_t) +#define PMU_IOC_GRAB_BACKLIGHT32 _IOR('B', 6, compat_size_t) + +static long compat_pmu_ioctl (struct file *filp, u_int cmd, u_long arg) +{ + switch (cmd) { + case PMU_IOC_SLEEP: + break; + case PMU_IOC_GET_BACKLIGHT32: + cmd = PMU_IOC_GET_BACKLIGHT; + break; + case PMU_IOC_SET_BACKLIGHT32: + cmd = PMU_IOC_SET_BACKLIGHT; + break; + case PMU_IOC_GET_MODEL32: + cmd = PMU_IOC_GET_MODEL; + break; + case PMU_IOC_HAS_ADB32: + cmd = PMU_IOC_HAS_ADB; + break; + case PMU_IOC_CAN_SLEEP32: + cmd = PMU_IOC_CAN_SLEEP; + break; + case PMU_IOC_GRAB_BACKLIGHT32: + cmd = PMU_IOC_GRAB_BACKLIGHT; + break; + default: + return -ENOIOCTLCMD; + } + return pmu_unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + static const struct file_operations pmu_device_fops = { .read = pmu_read, .write = pmu_write, .poll = pmu_fpoll, .unlocked_ioctl = pmu_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = compat_pmu_ioctl, +#endif .open = pmu_open, .release = pmu_release, }; diff --git a/drivers/md/.gitignore b/drivers/md/.gitignore deleted file mode 100644 index a7afec6b19c6..000000000000 --- a/drivers/md/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -mktables -raid6altivec*.c -raid6int*.c -raid6tables.c diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 1ba1e122e948..e4fb58db5454 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1000,10 +1000,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) page = bitmap->sb_page; offset = sizeof(bitmap_super_t); if (!file) - read_sb_page(bitmap->mddev, - bitmap->mddev->bitmap_info.offset, - page, - index, count); + page = read_sb_page( + bitmap->mddev, + bitmap->mddev->bitmap_info.offset, + page, + index, count); } else if (file) { page = read_page(file, index, bitmap, count); offset = 0; @@ -1542,8 +1543,7 @@ void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) atomic_read(&bitmap->mddev->recovery_active) == 0); bitmap->mddev->curr_resync_completed = bitmap->mddev->curr_resync; - if (bitmap->mddev->persistent) - set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags); + set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags); sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1); s = 0; while (s < sector && s < bitmap->mddev->resync_max_sectors) { diff --git a/drivers/md/md.c b/drivers/md/md.c index 3640f025cb72..ed075d19db37 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1578,7 +1578,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; if (rdev->sb_size & bmask) rdev->sb_size = (rdev->sb_size | bmask) + 1; - } + } else + max_dev = le32_to_cpu(sb->max_dev); + for (i=0; i<max_dev;i++) sb->dev_roles[i] = cpu_to_le16(0xfffe); @@ -2102,9 +2104,9 @@ repeat: rdev->recovery_offset = mddev->curr_resync_completed; } - if (mddev->external || !mddev->persistent) { - clear_bit(MD_CHANGE_DEVS, &mddev->flags); + if (!mddev->persistent) { clear_bit(MD_CHANGE_CLEAN, &mddev->flags); + clear_bit(MD_CHANGE_DEVS, &mddev->flags); wake_up(&mddev->sb_wait); return; } @@ -2113,7 +2115,6 @@ repeat: mddev->utime = get_seconds(); - set_bit(MD_CHANGE_PENDING, &mddev->flags); if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags)) force_change = 1; if (test_and_clear_bit(MD_CHANGE_CLEAN, &mddev->flags)) @@ -3306,7 +3307,7 @@ array_state_show(mddev_t *mddev, char *page) case 0: if (mddev->in_sync) st = clean; - else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags)) + else if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) st = write_pending; else if (mddev->safemode) st = active_idle; @@ -3387,9 +3388,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) mddev->in_sync = 1; if (mddev->safemode == 1) mddev->safemode = 0; - if (mddev->persistent) - set_bit(MD_CHANGE_CLEAN, - &mddev->flags); + set_bit(MD_CHANGE_CLEAN, &mddev->flags); } err = 0; } else @@ -3401,8 +3400,7 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) case active: if (mddev->pers) { restart_array(mddev); - if (mddev->external) - clear_bit(MD_CHANGE_CLEAN, &mddev->flags); + clear_bit(MD_CHANGE_PENDING, &mddev->flags); wake_up(&mddev->sb_wait); err = 0; } else { @@ -6505,6 +6503,7 @@ void md_write_start(mddev_t *mddev, struct bio *bi) if (mddev->in_sync) { mddev->in_sync = 0; set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_PENDING, &mddev->flags); md_wakeup_thread(mddev->thread); did_change = 1; } @@ -6513,7 +6512,6 @@ void md_write_start(mddev_t *mddev, struct bio *bi) if (did_change) sysfs_notify_dirent_safe(mddev->sysfs_state); wait_event(mddev->sb_wait, - !test_bit(MD_CHANGE_CLEAN, &mddev->flags) && !test_bit(MD_CHANGE_PENDING, &mddev->flags)); } @@ -6549,6 +6547,7 @@ int md_allow_write(mddev_t *mddev) if (mddev->in_sync) { mddev->in_sync = 0; set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_PENDING, &mddev->flags); if (mddev->safemode_delay && mddev->safemode == 0) mddev->safemode = 1; @@ -6558,7 +6557,7 @@ int md_allow_write(mddev_t *mddev) } else spin_unlock_irq(&mddev->write_lock); - if (test_bit(MD_CHANGE_CLEAN, &mddev->flags)) + if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) return -EAGAIN; else return 0; @@ -6756,8 +6755,7 @@ void md_do_sync(mddev_t *mddev) atomic_read(&mddev->recovery_active) == 0); mddev->curr_resync_completed = mddev->curr_resync; - if (mddev->persistent) - set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_CLEAN, &mddev->flags); sysfs_notify(&mddev->kobj, NULL, "sync_completed"); } @@ -7006,7 +7004,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) return; if ( ! ( - (mddev->flags && !mddev->external) || + (mddev->flags & ~ (1<<MD_CHANGE_PENDING)) || test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || test_bit(MD_RECOVERY_DONE, &mddev->recovery) || (mddev->external == 0 && mddev->safemode == 1) || @@ -7036,8 +7034,7 @@ void md_check_recovery(mddev_t *mddev) mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; did_change = 1; - if (mddev->persistent) - set_bit(MD_CHANGE_CLEAN, &mddev->flags); + set_bit(MD_CHANGE_CLEAN, &mddev->flags); } if (mddev->safemode == 1) mddev->safemode = 0; diff --git a/drivers/md/md.h b/drivers/md/md.h index d8e2ab25103b..112a2c32db0c 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -139,7 +139,7 @@ struct mddev_s unsigned long flags; #define MD_CHANGE_DEVS 0 /* Some device status has changed */ #define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */ -#define MD_CHANGE_PENDING 2 /* superblock update in progress */ +#define MD_CHANGE_PENDING 2 /* switch from 'clean' to 'active' in progress */ int suspended; atomic_t active_io; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 886a9d865488..378a25894c57 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1781,7 +1781,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* take from bio_init */ bio->bi_next = NULL; + bio->bi_flags &= ~(BIO_POOL_MASK-1); bio->bi_flags |= 1 << BIO_UPTODATE; + bio->bi_comp_cpu = -1; bio->bi_rw = READ; bio->bi_vcnt = 0; bio->bi_idx = 0; @@ -1854,7 +1856,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) break; BUG_ON(sync_blocks < (PAGE_SIZE>>9)); - if (len > (sync_blocks<<9)) + if ((len >> 9) > sync_blocks) len = sync_blocks<<9; } diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 7e82a9df726b..7961d59f5cac 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -319,7 +319,7 @@ static void ir_timer_keyup(unsigned long cookie) * a keyup event might follow immediately after the keydown. */ spin_lock_irqsave(&ir->keylock, flags); - if (time_is_after_eq_jiffies(ir->keyup_jiffies)) + if (time_is_before_eq_jiffies(ir->keyup_jiffies)) ir_keyup(ir); spin_unlock_irqrestore(&ir->keylock, flags); } @@ -510,6 +510,13 @@ int __ir_input_register(struct input_dev *input_dev, (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? " in raw mode" : ""); + /* + * Default delay of 250ms is too short for some protocols, expecially + * since the timeout is currently set to 250ms. Increase it to 500ms, + * to avoid wrong repetition of the keycodes. + */ + input_dev->rep[REP_DELAY] = 500; + return 0; out_event: diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 77b5946413c0..e63f757d5d72 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c @@ -267,7 +267,7 @@ static int ir_lirc_register(struct input_dev *input_dev) features |= LIRC_CAN_SET_SEND_CARRIER; if (ir_dev->props->s_tx_duty_cycle) - features |= LIRC_CAN_SET_REC_DUTY_CYCLE; + features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; } if (ir_dev->props->s_rx_carrier_range) diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 43094e7eccfa..8e0e1b1f8c87 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c @@ -279,9 +279,11 @@ int ir_raw_event_register(struct input_dev *input_dev) "rc%u", (unsigned int)ir->devno); if (IS_ERR(ir->raw->thread)) { + int ret = PTR_ERR(ir->raw->thread); + kfree(ir->raw); ir->raw = NULL; - return PTR_ERR(ir->raw->thread); + return ret; } mutex_lock(&ir_raw_handler_lock); diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c index 96dafc425c8e..46d42467f9b4 100644 --- a/drivers/media/IR/ir-sysfs.c +++ b/drivers/media/IR/ir-sysfs.c @@ -67,13 +67,14 @@ static ssize_t show_protocols(struct device *d, char *tmp = buf; int i; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { enabled = ir_dev->rc_tab.ir_type; allowed = ir_dev->props->allowed_protos; - } else { + } else if (ir_dev->raw) { enabled = ir_dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return sprintf(tmp, "[builtin]\n"); IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, @@ -121,10 +122,14 @@ static ssize_t store_protocols(struct device *d, int rc, i, count = 0; unsigned long flags; - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) type = ir_dev->rc_tab.ir_type; - else + else if (ir_dev->raw) type = ir_dev->raw->enabled_protocols; + else { + IR_dprintk(1, "Protocol switching not supported\n"); + return -EINVAL; + } while ((tmp = strsep((char **) &data, " \n")) != NULL) { if (!*tmp) @@ -185,7 +190,7 @@ static ssize_t store_protocols(struct device *d, } } - if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { + if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) { spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); ir_dev->rc_tab.ir_type = type; spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); diff --git a/drivers/media/IR/keymaps/rc-rc6-mce.c b/drivers/media/IR/keymaps/rc-rc6-mce.c index 64264f7f838f..39557ad401b6 100644 --- a/drivers/media/IR/keymaps/rc-rc6-mce.c +++ b/drivers/media/IR/keymaps/rc-rc6-mce.c @@ -19,6 +19,7 @@ static struct ir_scancode rc6_mce[] = { { 0x800f0416, KEY_PLAY }, { 0x800f0418, KEY_PAUSE }, + { 0x800f046e, KEY_PLAYPAUSE }, { 0x800f0419, KEY_STOP }, { 0x800f0417, KEY_RECORD }, @@ -37,6 +38,8 @@ static struct ir_scancode rc6_mce[] = { { 0x800f0411, KEY_VOLUMEDOWN }, { 0x800f0412, KEY_CHANNELUP }, { 0x800f0413, KEY_CHANNELDOWN }, + { 0x800f043a, KEY_BRIGHTNESSUP }, + { 0x800f0480, KEY_BRIGHTNESSDOWN }, { 0x800f0401, KEY_NUMERIC_1 }, { 0x800f0402, KEY_NUMERIC_2 }, diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c index ac6bb2c01a48..bc620e10ef77 100644 --- a/drivers/media/IR/mceusb.c +++ b/drivers/media/IR/mceusb.c @@ -120,6 +120,10 @@ static struct usb_device_id mceusb_dev_table[] = { { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, /* Philips eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, + /* Philips/Spinel plus IR transceiver for ASUS */ + { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, /* Realtek MCE IR Receiver */ { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, /* SMK/Toshiba G83C0004D410 */ diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index fe818348b8a3..48397f103d32 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -673,9 +673,6 @@ static int dib0700_probe(struct usb_interface *intf, else dev->props.rc.core.bulk_mode = false; - /* Need a higher delay, to avoid wrong repeat */ - dev->rc_input_dev->rep[REP_DELAY] = 500; - dib0700_rc_setup(dev); return 0; diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index f634d2e784b2..e06acd1fecb6 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -940,6 +940,58 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe == NULL ? -ENODEV : 0; } +/* STK7770P */ +static struct dib7000p_config dib7770p_dib7000p_config = { + .output_mpeg2_in_188_bytes = 1, + + .agc_config_count = 1, + .agc = &dib7070_agc_config, + .bw = &dib7070_bw_config_12_mhz, + .tuner_is_baseband = 1, + .spur_protect = 1, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .hostbus_diversity = 1, + .enable_current_mirror = 1, + .disable_sample_and_hold = 0, +}; + +static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct usb_device_descriptor *p = &adap->dev->udev->descriptor; + if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) && + p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E)) + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); + else + dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); + + dib0700_ctrl_clock(adap->dev, 72, 1); + + msleep(10); + dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); + msleep(10); + dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); + + if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, + &dib7770p_dib7000p_config) != 0) { + err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", + __func__); + return -ENODEV; + } + + adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, + &dib7770p_dib7000p_config); + return adap->fe == NULL ? -ENODEV : 0; +} + /* DIB807x generic */ static struct dibx000_agc_config dib807x_agc_config[2] = { { @@ -1781,7 +1833,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 60 */{ USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_XXS_2) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XPVR) }, { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK807XP) }, - { USB_DEVICE(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD) }, + { USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) }, { USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) }, /* 65 */{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV73ESE) }, { USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV282E) }, @@ -2406,7 +2458,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { .pid_filter_count = 32, .pid_filter = stk70x0p_pid_filter, .pid_filter_ctrl = stk70x0p_pid_filter_ctrl, - .frontend_attach = stk7070p_frontend_attach, + .frontend_attach = stk7770p_frontend_attach, .tuner_attach = dib7770p_tuner_attach, DIB0700_DEFAULT_STREAMING_CONFIG(0x02), diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c index 6b22ec64ab0c..f896337b4535 100644 --- a/drivers/media/dvb/dvb-usb/opera1.c +++ b/drivers/media/dvb/dvb-usb/opera1.c @@ -483,9 +483,7 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev, } } kfree(p); - if (fw) { - release_firmware(fw); - } + release_firmware(fw); return ret; } diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 2e28b973dfd3..3aed0d433921 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -260,6 +260,9 @@ static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_ad // dprintk( "908: %x, 909: %x\n", reg_908, reg_909); + reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4; + reg_908 |= (state->cfg.enable_current_mirror & 1) << 7; + dib7000p_write_word(state, 908, reg_908); dib7000p_write_word(state, 909, reg_909); } @@ -778,7 +781,10 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte default: case GUARD_INTERVAL_1_32: value *= 1; break; } - state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO + if (state->cfg.diversity_delay == 0) + state->div_sync_wait = (value * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo + else + state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for one DVSY-fifo /* deactive the possibility of diversity reception if extended interleaver */ state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K; diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h index 805dd13a97ee..da17345bf5bd 100644 --- a/drivers/media/dvb/frontends/dib7000p.h +++ b/drivers/media/dvb/frontends/dib7000p.h @@ -33,6 +33,11 @@ struct dib7000p_config { int (*agc_control) (struct dvb_frontend *, u8 before); u8 output_mode; + u8 disable_sample_and_hold : 1; + + u8 enable_current_mirror : 1; + u8 diversity_delay; + }; #define DEFAULT_DIB7000P_I2C_ADDRESS 18 diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index decdeda840d0..fd0830ed10d8 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -1,6 +1,6 @@ config MANTIS_CORE tristate "Mantis/Hopper PCI bridge based devices" - depends on PCI && I2C && INPUT + depends on PCI && I2C && INPUT && IR_CORE help Support for PCI cards based on the Mantis and Hopper PCi bridge. diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index d93468cd3a85..ff3b0fa901b3 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c @@ -1098,33 +1098,26 @@ EXPORT_SYMBOL_GPL(smscore_onresponse); * * @return pointer to descriptor on success, NULL on error. */ -struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) + +struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev) { struct smscore_buffer_t *cb = NULL; unsigned long flags; - DEFINE_WAIT(wait); - spin_lock_irqsave(&coredev->bufferslock, flags); - - /* This function must return a valid buffer, since the buffer list is - * finite, we check that there is an available buffer, if not, we wait - * until such buffer become available. - */ - - prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); - if (list_empty(&coredev->buffers)) { - spin_unlock_irqrestore(&coredev->bufferslock, flags); - schedule(); - spin_lock_irqsave(&coredev->bufferslock, flags); + if (!list_empty(&coredev->buffers)) { + cb = (struct smscore_buffer_t *) coredev->buffers.next; + list_del(&cb->entry); } + spin_unlock_irqrestore(&coredev->bufferslock, flags); + return cb; +} - finish_wait(&coredev->buffer_mng_waitq, &wait); - - cb = (struct smscore_buffer_t *) coredev->buffers.next; - list_del(&cb->entry); +struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) +{ + struct smscore_buffer_t *cb = NULL; - spin_unlock_irqrestore(&coredev->bufferslock, flags); + wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev))); return cb; } diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 67a4ec8768a6..4ce541a5eb47 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -395,7 +395,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, radio->registers[POWERCFG] = POWERCFG_ENABLE; if (si470x_set_register(radio, POWERCFG) < 0) { retval = -EIO; - goto err_all; + goto err_video; } msleep(110); diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile index 755dd0ce65ff..6f2b57384488 100644 --- a/drivers/media/video/cx231xx/Makefile +++ b/drivers/media/video/cx231xx/Makefile @@ -11,4 +11,5 @@ EXTRA_CFLAGS += -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/common/tuners EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-usb diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 6bdc0ef18119..f2a4900014bc 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c @@ -32,6 +32,7 @@ #include <media/v4l2-chip-ident.h> #include <media/cx25840.h> +#include "dvb-usb-ids.h" #include "xc5000.h" #include "cx231xx.h" @@ -175,6 +176,8 @@ struct usb_device_id cx231xx_id_table[] = { .driver_info = CX231XX_BOARD_CNXT_RDE_250}, {USB_DEVICE(0x0572, 0x58A1), .driver_info = CX231XX_BOARD_CNXT_RDU_250}, + {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff), + .driver_info = CX231XX_BOARD_UNKNOWN}, {}, }; @@ -226,14 +229,16 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) dev->board.name, dev->model); /* set the direction for GPIO pins */ - cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); - cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); + if (dev->board.tuner_gpio) { + cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1); + cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); - /* request some modules if any required */ + /* request some modules if any required */ - /* reset the Tuner */ - cx231xx_gpio_set(dev, dev->board.tuner_gpio); + /* reset the Tuner */ + cx231xx_gpio_set(dev, dev->board.tuner_gpio); + } /* set the mode to Analog mode initially */ cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 86ca8c2359dd..f5a3e74c3c7c 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -1996,7 +1996,7 @@ static int cx25840_probe(struct i2c_client *client, state->volume = v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME, - 0, 65335, 65535 / 100, default_volume); + 0, 65535, 65535 / 100, default_volume); state->mute = v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0); diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 99dbae117591..0fa85cbefbb1 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -17,7 +17,7 @@ config VIDEO_CX88 config VIDEO_CX88_ALSA tristate "Conexant 2388x DMA audio support" - depends on VIDEO_CX88 && SND && EXPERIMENTAL + depends on VIDEO_CX88 && SND select SND_PCM ---help--- This is a video4linux driver for direct (DMA) audio on diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index b9846106913e..78abc1c1f9d5 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -223,6 +223,7 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev, usb_rcvintpipe(dev, ep->bEndpointAddress), buffer, buffer_len, int_irq, (void *)gspca_dev, interval); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; gspca_dev->int_urb = urb; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 83a718f0f3f9..9052d5702556 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2357,8 +2357,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, (data[33] << 10); avg_lum >>= 9; atomic_set(&sd->avg_lum, avg_lum); - gspca_frame_add(gspca_dev, LAST_PACKET, - data, len); + gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0); return; } if (gspca_dev->last_packet_type == LAST_PACKET) { diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index be03a712731c..f0316d02f09f 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -466,6 +466,8 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar struct fb_vblank vblank; u32 trace; + memset(&vblank, 0, sizeof(struct fb_vblank)); + vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC; trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16; diff --git a/drivers/media/video/mem2mem_testdev.c b/drivers/media/video/mem2mem_testdev.c index 4525335f9bd4..a7210d981388 100644 --- a/drivers/media/video/mem2mem_testdev.c +++ b/drivers/media/video/mem2mem_testdev.c @@ -239,7 +239,7 @@ static int device_process(struct m2mtest_ctx *ctx, return -EFAULT; } - if (in_buf->vb.size < out_buf->vb.size) { + if (in_buf->vb.size > out_buf->vb.size) { v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n"); return -EINVAL; } @@ -1014,6 +1014,7 @@ static int m2mtest_remove(struct platform_device *pdev) v4l2_m2m_release(dev->m2m_dev); del_timer_sync(&dev->timer); video_unregister_device(dev->vfd); + video_device_release(dev->vfd); v4l2_device_unregister(&dev->v4l2_dev); kfree(dev); diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 758a4db27d65..c71af4e0e517 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -447,6 +447,9 @@ static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", __func__, rect.left, rect.top, rect.width, rect.height); + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + ret = mt9m111_make_rect(client, &rect); if (!ret) mt9m111->rect = rect; @@ -466,12 +469,14 @@ static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) { + if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + a->bounds.left = MT9M111_MIN_DARK_COLS; a->bounds.top = MT9M111_MIN_DARK_ROWS; a->bounds.width = MT9M111_MAX_WIDTH; a->bounds.height = MT9M111_MAX_HEIGHT; a->defrect = a->bounds; - a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; a->pixelaspect.numerator = 1; a->pixelaspect.denominator = 1; @@ -487,6 +492,7 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd, mf->width = mt9m111->rect.width; mf->height = mt9m111->rect.height; mf->code = mt9m111->fmt->code; + mf->colorspace = mt9m111->fmt->colorspace; mf->field = V4L2_FIELD_NONE; return 0; diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index e7cd23cd6394..b48473c7896b 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -402,9 +402,6 @@ static int mt9v022_s_fmt(struct v4l2_subdev *sd, if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC) return -EINVAL; break; - case 0: - /* No format change, only geometry */ - break; default: return -EINVAL; } diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index 66ff174151b5..b6ea67221d1d 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -378,6 +378,9 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, spin_lock_irqsave(&pcdev->lock, flags); + if (*fb_active == NULL) + goto out; + vb = &(*fb_active)->vb; dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -402,6 +405,7 @@ static void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, *fb_active = buf; +out: spin_unlock_irqrestore(&pcdev->lock, flags); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c index 1b992b847198..55ea914c7fcd 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -513,7 +513,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, if (ret >= 0) { ret = pvr2_ctrl_range_check(cptr,*valptr); } - if (maskptr) *maskptr = ~0; + *maskptr = ~0; } else if (cptr->info->type == pvr2_ctl_bool) { ret = parse_token(ptr,len,valptr,boolNames, ARRAY_SIZE(boolNames)); @@ -522,7 +522,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, } else if (ret == 0) { *valptr = (*valptr & 1) ? !0 : 0; } - if (maskptr) *maskptr = 1; + *maskptr = 1; } else if (cptr->info->type == pvr2_ctl_enum) { ret = parse_token( ptr,len,valptr, @@ -531,7 +531,7 @@ int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, if (ret >= 0) { ret = pvr2_ctrl_range_check(cptr,*valptr); } - if (maskptr) *maskptr = ~0; + *maskptr = ~0; } else if (cptr->info->type == pvr2_ctl_bitmask) { ret = parse_tlist( ptr,len,maskptr,valptr, diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index b151c7be8a50..6961c55baf9b 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c @@ -393,6 +393,37 @@ static void fimc_set_yuv_order(struct fimc_ctx *ctx) dbg("ctx->out_order_1p= %d", ctx->out_order_1p); } +static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f) +{ + struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; + + f->dma_offset.y_h = f->offs_h; + if (!variant->pix_hoff) + f->dma_offset.y_h *= (f->fmt->depth >> 3); + + f->dma_offset.y_v = f->offs_v; + + f->dma_offset.cb_h = f->offs_h; + f->dma_offset.cb_v = f->offs_v; + + f->dma_offset.cr_h = f->offs_h; + f->dma_offset.cr_v = f->offs_v; + + if (!variant->pix_hoff) { + if (f->fmt->planes_cnt == 3) { + f->dma_offset.cb_h >>= 1; + f->dma_offset.cr_h >>= 1; + } + if (f->fmt->color == S5P_FIMC_YCBCR420) { + f->dma_offset.cb_v >>= 1; + f->dma_offset.cr_v >>= 1; + } + } + + dbg("in_offset: color= %d, y_h= %d, y_v= %d", + f->fmt->color, f->dma_offset.y_h, f->dma_offset.y_v); +} + /** * fimc_prepare_config - check dimensions, operation and color mode * and pre-calculate offset and the scaling coefficients. @@ -406,7 +437,6 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) { struct fimc_frame *s_frame, *d_frame; struct fimc_vid_buffer *buf = NULL; - struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; int ret = 0; s_frame = &ctx->s_frame; @@ -419,61 +449,16 @@ static int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags) swap(d_frame->width, d_frame->height); } - /* Prepare the output offset ratios for scaler. */ - d_frame->dma_offset.y_h = d_frame->offs_h; - if (!variant->pix_hoff) - d_frame->dma_offset.y_h *= (d_frame->fmt->depth >> 3); - - d_frame->dma_offset.y_v = d_frame->offs_v; - - d_frame->dma_offset.cb_h = d_frame->offs_h; - d_frame->dma_offset.cb_v = d_frame->offs_v; - - d_frame->dma_offset.cr_h = d_frame->offs_h; - d_frame->dma_offset.cr_v = d_frame->offs_v; + /* Prepare the DMA offset ratios for scaler. */ + fimc_prepare_dma_offset(ctx, &ctx->s_frame); + fimc_prepare_dma_offset(ctx, &ctx->d_frame); - if (!variant->pix_hoff && d_frame->fmt->planes_cnt == 3) { - d_frame->dma_offset.cb_h >>= 1; - d_frame->dma_offset.cb_v >>= 1; - d_frame->dma_offset.cr_h >>= 1; - d_frame->dma_offset.cr_v >>= 1; - } - - dbg("out offset: color= %d, y_h= %d, y_v= %d", - d_frame->fmt->color, - d_frame->dma_offset.y_h, d_frame->dma_offset.y_v); - - /* Prepare the input offset ratios for scaler. */ - s_frame->dma_offset.y_h = s_frame->offs_h; - if (!variant->pix_hoff) - s_frame->dma_offset.y_h *= (s_frame->fmt->depth >> 3); - s_frame->dma_offset.y_v = s_frame->offs_v; - - s_frame->dma_offset.cb_h = s_frame->offs_h; - s_frame->dma_offset.cb_v = s_frame->offs_v; - - s_frame->dma_offset.cr_h = s_frame->offs_h; - s_frame->dma_offset.cr_v = s_frame->offs_v; - - if (!variant->pix_hoff && s_frame->fmt->planes_cnt == 3) { - s_frame->dma_offset.cb_h >>= 1; - s_frame->dma_offset.cb_v >>= 1; - s_frame->dma_offset.cr_h >>= 1; - s_frame->dma_offset.cr_v >>= 1; - } - - dbg("in offset: color= %d, y_h= %d, y_v= %d", - s_frame->fmt->color, s_frame->dma_offset.y_h, - s_frame->dma_offset.y_v); - - fimc_set_yuv_order(ctx); - - /* Check against the scaler ratio. */ if (s_frame->height > (SCALER_MAX_VRATIO * d_frame->height) || s_frame->width > (SCALER_MAX_HRATIO * d_frame->width)) { err("out of scaler range"); return -EINVAL; } + fimc_set_yuv_order(ctx); } /* Input DMA mode is not allowed when the scaler is disabled. */ @@ -822,7 +807,8 @@ static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f) } else { v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev, "Wrong buffer/video queue type (%d)\n", f->type); - return -EINVAL; + ret = -EINVAL; + goto s_fmt_out; } pix = &f->fmt.pix; @@ -1414,8 +1400,10 @@ static int fimc_probe(struct platform_device *pdev) } fimc->work_queue = create_workqueue(dev_name(&fimc->pdev->dev)); - if (!fimc->work_queue) + if (!fimc->work_queue) { + ret = -ENOMEM; goto err_irq; + } ret = fimc_register_m2m_device(fimc); if (ret) @@ -1492,6 +1480,7 @@ static struct samsung_fimc_variant fimc2_variant_s5p = { }; static struct samsung_fimc_variant fimc01_variant_s5pv210 = { + .pix_hoff = 1, .has_inp_rot = 1, .has_out_rot = 1, .min_inp_pixsize = 16, @@ -1506,6 +1495,7 @@ static struct samsung_fimc_variant fimc01_variant_s5pv210 = { }; static struct samsung_fimc_variant fimc2_variant_s5pv210 = { + .pix_hoff = 1, .min_inp_pixsize = 16, .min_out_pixsize = 32, diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index ec697fcd406e..bb8d83d8ddaf 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4323,13 +4323,13 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { /* Beholder Intl. Ltd. 2008 */ - /*Dmitry Belimov <d.belimov@gmail.com> */ - .name = "Beholder BeholdTV Columbus TVFM", + /* Dmitry Belimov <d.belimov@gmail.com> */ + .name = "Beholder BeholdTV Columbus TV/FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_ALPS_TSBE5_PAL, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, + .radio_type = TUNER_TEA5767, + .tuner_addr = 0xc2 >> 1, + .radio_addr = 0xc0 >> 1, .tda9887_conf = TDA9887_PRESENT, .gpiomask = 0x000A8004, .inputs = {{ diff --git a/drivers/media/video/saa7164/saa7164-buffer.c b/drivers/media/video/saa7164/saa7164-buffer.c index 5713f3a4b76c..ddd25d32723d 100644 --- a/drivers/media/video/saa7164/saa7164-buffer.c +++ b/drivers/media/video/saa7164/saa7164-buffer.c @@ -136,10 +136,11 @@ ret: int saa7164_buffer_dealloc(struct saa7164_tsport *port, struct saa7164_buffer *buf) { - struct saa7164_dev *dev = port->dev; + struct saa7164_dev *dev; - if ((buf == 0) || (port == 0)) + if (!buf || !port) return SAA_ERR_BAD_PARAMETER; + dev = port->dev; dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n", __func__, buf); diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 8bdd940f32e6..2ac85d8984f0 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c @@ -486,6 +486,12 @@ static int uvc_parse_format(struct uvc_device *dev, max(frame->dwFrameInterval[0], frame->dwDefaultFrameInterval)); + if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) { + frame->bFrameIntervalType = 1; + frame->dwFrameInterval[0] = + frame->dwDefaultFrameInterval; + } + uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n", frame->wWidth, frame->wHeight, 10000000/frame->dwDefaultFrameInterval, @@ -2026,6 +2032,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = 1, .bInterfaceProtocol = 0 }, + /* Chicony CNF7129 (Asus EEE 100HE) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x04f2, + .idProduct = 0xb071, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_RESTRICT_FRAME_RATE }, /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, @@ -2091,6 +2106,15 @@ static struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_PROBE_DEF }, + /* IMC Networks (Medion Akoya) */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x13d3, + .idProduct = 0x5103, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_STREAM_NO_FID }, /* Syntek (HP Spartan) */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index bdacf3beabf5..892e0e51916c 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -182,6 +182,7 @@ struct uvc_xu_control { #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_FIX_BANDWIDTH 0x00000080 #define UVC_QUIRK_PROBE_DEF 0x00000100 +#define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 diff --git a/drivers/media/video/videobuf-dma-contig.c b/drivers/media/video/videobuf-dma-contig.c index 372b87efcd05..6ff9e4bac3ea 100644 --- a/drivers/media/video/videobuf-dma-contig.c +++ b/drivers/media/video/videobuf-dma-contig.c @@ -393,8 +393,10 @@ void videobuf_dma_contig_free(struct videobuf_queue *q, } /* read() method */ - dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle); - mem->vaddr = NULL; + if (mem->vaddr) { + dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle); + mem->vaddr = NULL; + } } EXPORT_SYMBOL_GPL(videobuf_dma_contig_free); diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 06f9a9c2a39a..2ad0bc252b0e 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -94,7 +94,7 @@ err: * must free the memory. */ static struct scatterlist *videobuf_pages_to_sg(struct page **pages, - int nr_pages, int offset) + int nr_pages, int offset, size_t size) { struct scatterlist *sglist; int i; @@ -110,12 +110,14 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages, /* DMA to highmem pages might not work */ goto highmem; sg_set_page(&sglist[0], pages[0], PAGE_SIZE - offset, offset); + size -= PAGE_SIZE - offset; for (i = 1; i < nr_pages; i++) { if (NULL == pages[i]) goto nopage; if (PageHighMem(pages[i])) goto highmem; - sg_set_page(&sglist[i], pages[i], PAGE_SIZE, 0); + sg_set_page(&sglist[i], pages[i], min(PAGE_SIZE, size), 0); + size -= min(PAGE_SIZE, size); } return sglist; @@ -170,7 +172,8 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma, first = (data & PAGE_MASK) >> PAGE_SHIFT; last = ((data+size-1) & PAGE_MASK) >> PAGE_SHIFT; - dma->offset = data & ~PAGE_MASK; + dma->offset = data & ~PAGE_MASK; + dma->size = size; dma->nr_pages = last-first+1; dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL); if (NULL == dma->pages) @@ -252,7 +255,7 @@ int videobuf_dma_map(struct device *dev, struct videobuf_dmabuf *dma) if (dma->pages) { dma->sglist = videobuf_pages_to_sg(dma->pages, dma->nr_pages, - dma->offset); + dma->offset, dma->size); } if (dma->vaddr) { dma->sglist = videobuf_vmalloc_to_sg(dma->vaddr, diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 04028a9ee082..428377a5a6f5 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -429,24 +429,25 @@ static void max8925_irq_sync_unlock(unsigned int irq) irq_tsc = cache_tsc; for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) { irq_data = &max8925_irqs[i]; + /* 1 -- disable, 0 -- enable */ switch (irq_data->mask_reg) { case MAX8925_CHG_IRQ1_MASK: - irq_chg[0] &= irq_data->enable; + irq_chg[0] &= ~irq_data->enable; break; case MAX8925_CHG_IRQ2_MASK: - irq_chg[1] &= irq_data->enable; + irq_chg[1] &= ~irq_data->enable; break; case MAX8925_ON_OFF_IRQ1_MASK: - irq_on[0] &= irq_data->enable; + irq_on[0] &= ~irq_data->enable; break; case MAX8925_ON_OFF_IRQ2_MASK: - irq_on[1] &= irq_data->enable; + irq_on[1] &= ~irq_data->enable; break; case MAX8925_RTC_IRQ_MASK: - irq_rtc &= irq_data->enable; + irq_rtc &= ~irq_data->enable; break; case MAX8925_TSC_IRQ_MASK: - irq_tsc &= irq_data->enable; + irq_tsc &= ~irq_data->enable; break; default: dev_err(chip->dev, "wrong IRQ\n"); diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 7dabe4dbd373..294183b6260b 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c @@ -394,8 +394,13 @@ static int wm831x_irq_set_type(unsigned int irq, unsigned int type) irq = irq - wm831x->irq_base; - if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) - return -EINVAL; + if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { + /* Ignore internal-only IRQs */ + if (irq >= 0 && irq < WM831X_NUM_IRQS) + return 0; + else + return -EINVAL; + } switch (type) { case IRQ_TYPE_EDGE_BOTH: diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0b591b658243..b74331260744 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -368,7 +368,7 @@ config VMWARE_BALLOON If unsure, say N. To compile this driver as a module, choose M here: the - module will be called vmware_balloon. + module will be called vmw_balloon. config ARM_CHARLCD bool "ARM Ltd. Character LCD Driver" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 255a80dc9d73..42eab95cde2a 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -33,5 +33,5 @@ obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ obj-$(CONFIG_HMC6352) += hmc6352.o obj-y += eeprom/ obj-y += cb710/ -obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o +obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c index 714c6b487313..d5f3a3fd2319 100644 --- a/drivers/misc/bh1780gli.c +++ b/drivers/misc/bh1780gli.c @@ -190,7 +190,6 @@ static int __devexit bh1780_remove(struct i2c_client *client) ddata = i2c_get_clientdata(client); sysfs_remove_group(&client->dev.kobj, &bh1780_attr_group); - i2c_set_clientdata(client, NULL); kfree(ddata); return 0; diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmw_balloon.c index 2a1e804a71aa..2a1e804a71aa 100644 --- a/drivers/misc/vmware_balloon.c +++ b/drivers/misc/vmw_balloon.c diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index bd2755e8d9a3..f332c52968b7 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -362,9 +362,8 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, goto err; } - err = mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid); - - if (!err) { + if (ocr & R4_MEMORY_PRESENT + && mmc_sd_get_cid(host, host->ocr & ocr, card->raw_cid) == 0) { card->type = MMC_TYPE_SD_COMBO; if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 5f3a599ead07..87226cd202a5 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -66,6 +66,7 @@ #include <linux/clk.h> #include <linux/atmel_pdc.h> #include <linux/gfp.h> +#include <linux/highmem.h> #include <linux/mmc/host.h> diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 9a68ff4353a2..5a950b16d9e6 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -148,11 +148,12 @@ static int imxmci_start_clock(struct imxmci_host *host) while (delay--) { reg = readw(host->base + MMC_REG_STATUS); - if (reg & STATUS_CARD_BUS_CLK_RUN) + if (reg & STATUS_CARD_BUS_CLK_RUN) { /* Check twice before cut */ reg = readw(host->base + MMC_REG_STATUS); if (reg & STATUS_CARD_BUS_CLK_RUN) return 0; + } if (test_bit(IMXMCI_PEND_STARTED_b, &host->pending_events)) return 0; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4a8776f8afdd..4526d2791f29 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2305,7 +2305,6 @@ static int omap_hsmmc_suspend(struct device *dev) int ret = 0; struct platform_device *pdev = to_platform_device(dev); struct omap_hsmmc_host *host = platform_get_drvdata(pdev); - pm_message_t state = PMSG_SUSPEND; /* unused by MMC core */ if (host && host->suspended) return 0; @@ -2324,8 +2323,8 @@ static int omap_hsmmc_suspend(struct device *dev) } } cancel_work_sync(&host->mmc_carddetect_work); - mmc_host_enable(host->mmc); ret = mmc_suspend_host(host->mmc); + mmc_host_enable(host->mmc); if (ret == 0) { omap_hsmmc_disable_irq(host); OMAP_HSMMC_WRITE(host->base, HCTL, diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 2e16e0a90a5e..976330de379e 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1600,7 +1600,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) host->pio_active = XFER_NONE; #ifdef CONFIG_MMC_S3C_PIODMA - host->dodma = host->pdata->dma; + host->dodma = host->pdata->use_dma; #endif host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 71ad4163b95e..aacb862ecc8a 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -241,8 +241,10 @@ static struct sdhci_ops sdhci_s3c_ops = { static void sdhci_s3c_notify_change(struct platform_device *dev, int state) { struct sdhci_host *host = platform_get_drvdata(dev); + unsigned long flags; + if (host) { - spin_lock(&host->lock); + spin_lock_irqsave(&host->lock, flags); if (state) { dev_dbg(&dev->dev, "card inserted.\n"); host->flags &= ~SDHCI_DEVICE_DEAD; @@ -253,7 +255,7 @@ static void sdhci_s3c_notify_change(struct platform_device *dev, int state) host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; } tasklet_schedule(&host->card_tasklet); - spin_unlock(&host->lock); + spin_unlock_irqrestore(&host->lock, flags); } } @@ -481,8 +483,10 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) sdhci_remove_host(host, 1); for (ptr = 0; ptr < 3; ptr++) { - clk_disable(sc->clk_bus[ptr]); - clk_put(sc->clk_bus[ptr]); + if (sc->clk_bus[ptr]) { + clk_disable(sc->clk_bus[ptr]); + clk_put(sc->clk_bus[ptr]); + } } clk_disable(sc->clk_io); clk_put(sc->clk_io); diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index ee7d0a5a51c4..69d98e3bf6ab 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -164,6 +164,7 @@ tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd) static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) { struct mmc_data *data = host->data; + void *sg_virt; unsigned short *buf; unsigned int count; unsigned long flags; @@ -173,8 +174,8 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) return; } - buf = (unsigned short *)(tmio_mmc_kmap_atomic(host, &flags) + - host->sg_off); + sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags); + buf = (unsigned short *)(sg_virt + host->sg_off); count = host->sg_ptr->length - host->sg_off; if (count > data->blksz) @@ -191,7 +192,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) host->sg_off += count; - tmio_mmc_kunmap_atomic(host, &flags); + tmio_mmc_kunmap_atomic(sg_virt, &flags); if (host->sg_off == host->sg_ptr->length) tmio_mmc_next_sg(host); diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 64f7d5dfc106..0fedc78e3ea5 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -82,10 +82,7 @@ #define ack_mmc_irqs(host, i) \ do { \ - u32 mask;\ - mask = sd_ctrl_read32((host), CTL_STATUS); \ - mask &= ~((i) & TMIO_MASK_IRQ); \ - sd_ctrl_write32((host), CTL_STATUS, mask); \ + sd_ctrl_write32((host), CTL_STATUS, ~(i)); \ } while (0) @@ -177,19 +174,17 @@ static inline int tmio_mmc_next_sg(struct tmio_mmc_host *host) return --host->sg_len; } -static inline char *tmio_mmc_kmap_atomic(struct tmio_mmc_host *host, +static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags) { - struct scatterlist *sg = host->sg_ptr; - local_irq_save(*flags); return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; } -static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host, +static inline void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags) { - kunmap_atomic(sg_page(host->sg_ptr), KM_BIO_SRC_IRQ); + kunmap_atomic(virt, KM_BIO_SRC_IRQ); local_irq_restore(*flags); } diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index a382e3dd0a5d..6fbeefa3a766 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -682,7 +682,6 @@ static int __devinit bf5xx_nand_add_partition(struct bf5xx_nand_info *info) static int __devexit bf5xx_nand_remove(struct platform_device *pdev) { struct bf5xx_nand_info *info = to_nand_info(pdev); - struct mtd_info *mtd = NULL; platform_set_drvdata(pdev, NULL); @@ -690,11 +689,7 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) * and their partitions, then go through freeing the * resources used */ - mtd = &info->mtd; - if (mtd) { - nand_release(mtd); - kfree(mtd); - } + nand_release(&info->mtd); peripheral_free_list(bfin_nfc_pin_req); bf5xx_nand_dma_remove(info); @@ -710,7 +705,7 @@ static int bf5xx_nand_scan(struct mtd_info *mtd) struct nand_chip *chip = mtd->priv; int ret; - ret = nand_scan_ident(mtd, 1); + ret = nand_scan_ident(mtd, 1, NULL); if (ret) return ret; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index fcf8ceb277d4..b2828e84d243 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -67,7 +67,9 @@ #define NFC_V1_V2_CONFIG1_BIG (1 << 5) #define NFC_V1_V2_CONFIG1_RST (1 << 6) #define NFC_V1_V2_CONFIG1_CE (1 << 7) -#define NFC_V1_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_ONE_CYCLE (1 << 8) +#define NFC_V2_CONFIG1_PPB(x) (((x) & 0x3) << 9) +#define NFC_V2_CONFIG1_FP_INT (1 << 11) #define NFC_V1_V2_CONFIG2_INT (1 << 15) @@ -402,16 +404,16 @@ static void send_read_id_v1_v2(struct mxc_nand_host *host) /* Wait for operation to complete */ wait_op_done(host, true); + memcpy(host->data_buf, host->main_area0, 16); + if (this->options & NAND_BUSWIDTH_16) { - void __iomem *main_buf = host->main_area0; /* compress the ID info */ - writeb(readb(main_buf + 2), main_buf + 1); - writeb(readb(main_buf + 4), main_buf + 2); - writeb(readb(main_buf + 6), main_buf + 3); - writeb(readb(main_buf + 8), main_buf + 4); - writeb(readb(main_buf + 10), main_buf + 5); + host->data_buf[1] = host->data_buf[2]; + host->data_buf[2] = host->data_buf[4]; + host->data_buf[3] = host->data_buf[6]; + host->data_buf[4] = host->data_buf[8]; + host->data_buf[5] = host->data_buf[10]; } - memcpy(host->data_buf, host->main_area0, 16); } static uint16_t get_dev_status_v3(struct mxc_nand_host *host) @@ -729,27 +731,30 @@ static void preset_v1_v2(struct mtd_info *mtd) { struct nand_chip *nand_chip = mtd->priv; struct mxc_nand_host *host = nand_chip->priv; - uint16_t tmp; - - /* enable interrupt, disable spare enable */ - tmp = readw(NFC_V1_V2_CONFIG1); - tmp &= ~NFC_V1_V2_CONFIG1_INT_MSK; - tmp &= ~NFC_V1_V2_CONFIG1_SP_EN; - if (nand_chip->ecc.mode == NAND_ECC_HW) { - tmp |= NFC_V1_V2_CONFIG1_ECC_EN; - } else { - tmp &= ~NFC_V1_V2_CONFIG1_ECC_EN; - } + uint16_t config1 = 0; + + if (nand_chip->ecc.mode == NAND_ECC_HW) + config1 |= NFC_V1_V2_CONFIG1_ECC_EN; + + if (nfc_is_v21()) + config1 |= NFC_V2_CONFIG1_FP_INT; + + if (!cpu_is_mx21()) + config1 |= NFC_V1_V2_CONFIG1_INT_MSK; if (nfc_is_v21() && mtd->writesize) { + uint16_t pages_per_block = mtd->erasesize / mtd->writesize; + host->eccsize = get_eccsize(mtd); if (host->eccsize == 4) - tmp |= NFC_V2_CONFIG1_ECC_MODE_4; + config1 |= NFC_V2_CONFIG1_ECC_MODE_4; + + config1 |= NFC_V2_CONFIG1_PPB(ffs(pages_per_block) - 6); } else { host->eccsize = 1; } - writew(tmp, NFC_V1_V2_CONFIG1); + writew(config1, NFC_V1_V2_CONFIG1); /* preset operation */ /* Unlock the internal RAM Buffer */ diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 133d51528f8d..513e0a76a4a7 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -413,7 +413,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT); } while (prefetch_status); /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(); + gpmc_prefetch_reset(info->gpmc_cs); dma_unmap_single(&info->pdev->dev, dma_addr, len, dir); return 0; diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 4d89f3780207..4d01cda68844 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -1320,6 +1320,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) goto fail_free_irq; } +#ifdef CONFIG_MTD_PARTITIONS if (mtd_has_cmdlinepart()) { static const char *probes[] = { "cmdlinepart", NULL }; struct mtd_partition *parts; @@ -1332,6 +1333,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) } return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); +#else + return 0; +#endif fail_free_irq: free_irq(irq, info); @@ -1364,7 +1368,9 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); del_mtd_device(mtd); +#ifdef CONFIG_MTD_PARTITIONS del_mtd_partitions(mtd); +#endif irq = platform_get_irq(pdev, 0); if (irq >= 0) free_irq(irq, info); diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index cb443af3d45f..a460f1b748c2 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -554,14 +554,13 @@ static int s5pc110_dma_ops(void *dst, void *src, size_t count, int direction) do { status = readl(base + S5PC110_DMA_TRANS_STATUS); + if (status & S5PC110_DMA_TRANS_STATUS_TE) { + writel(S5PC110_DMA_TRANS_CMD_TEC, + base + S5PC110_DMA_TRANS_CMD); + return -EIO; + } } while (!(status & S5PC110_DMA_TRANS_STATUS_TD)); - if (status & S5PC110_DMA_TRANS_STATUS_TE) { - writel(S5PC110_DMA_TRANS_CMD_TEC, base + S5PC110_DMA_TRANS_CMD); - writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); - return -EIO; - } - writel(S5PC110_DMA_TRANS_CMD_TDC, base + S5PC110_DMA_TRANS_CMD); return 0; @@ -571,13 +570,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, unsigned char *buffer, int offset, size_t count) { struct onenand_chip *this = mtd->priv; - void __iomem *bufferram; void __iomem *p; void *buf = (void *) buffer; dma_addr_t dma_src, dma_dst; int err; - p = bufferram = this->base + area; + p = this->base + area; if (ONENAND_CURRENT_BUFFERRAM(this)) { if (area == ONENAND_DATARAM) p += this->writesize; @@ -621,7 +619,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area, normal: if (count != mtd->writesize) { /* Copy the bufferram to memory to prevent unaligned access */ - memcpy(this->page_buf, bufferram, mtd->writesize); + memcpy(this->page_buf, p, mtd->writesize); p = this->page_buf + offset; } diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index 2246f154e2f7..61f6e5e40458 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug @@ -6,7 +6,7 @@ config MTD_UBI_DEBUG depends on SYSFS depends on MTD_UBI select DEBUG_FS - select KALLSYMS_ALL + select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL help This option enables UBI debugging. diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 4dfa6b90c21c..3d2d1a69e9a0 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -798,18 +798,18 @@ static int rename_volumes(struct ubi_device *ubi, goto out_free; } - re = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); - if (!re) { + re1 = kzalloc(sizeof(struct ubi_rename_entry), GFP_KERNEL); + if (!re1) { err = -ENOMEM; ubi_close_volume(desc); goto out_free; } - re->remove = 1; - re->desc = desc; - list_add(&re->list, &rename_list); + re1->remove = 1; + re1->desc = desc; + list_add(&re1->list, &rename_list); dbg_msg("will remove volume %d, name \"%s\"", - re->desc->vol->vol_id, re->desc->vol->name); + re1->desc->vol->vol_id, re1->desc->vol->name); } mutex_lock(&ubi->device_mutex); diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 372a15ac9995..69b52e9c9489 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -843,7 +843,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, case UBI_COMPAT_DELETE: ubi_msg("\"delete\" compatible internal volume %d:%d" " found, will remove it", vol_id, lnum); - err = add_to_list(si, pnum, ec, &si->corr); + err = add_to_list(si, pnum, ec, &si->erase); if (err) return err; return 0; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index ee7b1d8fbb92..97a435672eaf 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1212,7 +1212,8 @@ int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum) retry: spin_lock(&ubi->wl_lock); e = ubi->lookuptbl[pnum]; - if (e == ubi->move_from || in_wl_tree(e, &ubi->scrub)) { + if (e == ubi->move_from || in_wl_tree(e, &ubi->scrub) || + in_wl_tree(e, &ubi->erroneous)) { spin_unlock(&ubi->wl_lock); return 0; } diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index c754d88e5ec9..179871d9e71f 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -633,7 +633,11 @@ struct vortex_private { open:1, medialock:1, must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ - large_frames:1; /* accept large frames */ + large_frames:1, /* accept large frames */ + handling_irq:1; /* private in_irq indicator */ + /* {get|set}_wol operations are already serialized by rtnl. + * no additional locking is required for the enable_wol and acpi_set_WOL() + */ int drv_flags; u16 status_enable; u16 intr_enable; @@ -646,7 +650,7 @@ struct vortex_private { u16 io_size; /* Size of PCI region (for release_region) */ /* Serialises access to hardware other than MII and variables below. - * The lock hierarchy is rtnl_lock > lock > mii_lock > window_lock. */ + * The lock hierarchy is rtnl_lock > {lock, mii_lock} > window_lock. */ spinlock_t lock; spinlock_t mii_lock; /* Serialises access to MII */ @@ -1993,10 +1997,9 @@ vortex_error(struct net_device *dev, int status) } } - if (status & RxEarly) { /* Rx early is unused. */ - vortex_rx(dev); + if (status & RxEarly) /* Rx early is unused. */ iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD); - } + if (status & StatsFull) { /* Empty statistics. */ static int DoneDidThat; if (vortex_debug > 4) @@ -2133,6 +2136,15 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->name, vp->cur_tx); } + /* + * We can't allow a recursion from our interrupt handler back into the + * tx routine, as they take the same spin lock, and that causes + * deadlock. Just return NETDEV_TX_BUSY and let the stack try again in + * a bit + */ + if (vp->handling_irq) + return NETDEV_TX_BUSY; + if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) { if (vortex_debug > 0) pr_warning("%s: BUG! Tx Ring full, refusing to send buffer.\n", @@ -2288,7 +2300,12 @@ vortex_interrupt(int irq, void *dev_id) if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) { if (status == 0xffff) break; + if (status & RxEarly) + vortex_rx(dev); + spin_unlock(&vp->window_lock); vortex_error(dev, status); + spin_lock(&vp->window_lock); + window_set(vp, 7); } if (--work_done < 0) { @@ -2335,11 +2352,13 @@ boomerang_interrupt(int irq, void *dev_id) ioaddr = vp->ioaddr; + /* * It seems dopey to put the spinlock this early, but we could race against vortex_tx_timeout * and boomerang_start_xmit */ spin_lock(&vp->lock); + vp->handling_irq = 1; status = ioread16(ioaddr + EL3_STATUS); @@ -2447,6 +2466,7 @@ boomerang_interrupt(int irq, void *dev_id) pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status); handler_exit: + vp->handling_irq = 0; spin_unlock(&vp->lock); return IRQ_HANDLED; } @@ -2922,28 +2942,31 @@ static void vortex_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); - spin_lock_irq(&vp->lock); + if (!VORTEX_PCI(vp)) + return; + wol->supported = WAKE_MAGIC; wol->wolopts = 0; if (vp->enable_wol) wol->wolopts |= WAKE_MAGIC; - spin_unlock_irq(&vp->lock); } static int vortex_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct vortex_private *vp = netdev_priv(dev); + + if (!VORTEX_PCI(vp)) + return -EOPNOTSUPP; + if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; - spin_lock_irq(&vp->lock); if (wol->wolopts & WAKE_MAGIC) vp->enable_wol = 1; else vp->enable_wol = 0; acpi_set_WOL(dev); - spin_unlock_irq(&vp->lock); return 0; } @@ -2971,7 +2994,6 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { int err; struct vortex_private *vp = netdev_priv(dev); - unsigned long flags; pci_power_t state = 0; if(VORTEX_PCI(vp)) @@ -2981,9 +3003,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) if(state != 0) pci_set_power_state(VORTEX_PCI(vp), PCI_D0); - spin_lock_irqsave(&vp->lock, flags); err = generic_mii_ioctl(&vp->mii, if_mii(rq), cmd, NULL); - spin_unlock_irqrestore(&vp->lock, flags); if(state != 0) pci_set_power_state(VORTEX_PCI(vp), state); @@ -3188,6 +3208,9 @@ static void acpi_set_WOL(struct net_device *dev) return; } + if (VORTEX_PCI(vp)->current_state < PCI_D3hot) + return; + /* Change the power state to D3; RxEnable doesn't take effect. */ pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot); } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5a6895320b48..5db667c0b371 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -928,6 +928,16 @@ config SMC91X The module will be called smc91x. If you want to compile it as a module, say M here and read <file:Documentation/kbuild/modules.txt>. +config PXA168_ETH + tristate "Marvell pxa168 ethernet support" + depends on CPU_PXA168 + select PHYLIB + help + This driver supports the pxa168 Ethernet ports. + + To compile this driver as a module, choose M here. The module + will be called pxa168_eth. + config NET_NETX tristate "NetX Ethernet support" select MII @@ -2418,7 +2428,7 @@ config UGETH_TX_ON_DEMAND config MV643XX_ETH tristate "Marvell Discovery (643XX) and Orion ethernet support" - depends on MV64X60 || PPC32 || PLAT_ORION + depends on (MV64X60 || PPC32 || PLAT_ORION) && INET select INET_LRO select PHYLIB help @@ -2793,7 +2803,7 @@ config NIU config PASEMI_MAC tristate "PA Semi 1/10Gbit MAC" - depends on PPC_PASEMI && PCI + depends on PPC_PASEMI && PCI && INET select PHYLIB select INET_LRO help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 56e8c27f77ce..3e8f150c4b14 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -244,6 +244,7 @@ obj-$(CONFIG_MYRI10GE) += myri10ge/ obj-$(CONFIG_SMC91X) += smc91x.o obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_SMSC911X) += smsc911x.o +obj-$(CONFIG_PXA168_ETH) += pxa168_eth.o obj-$(CONFIG_BFIN_MAC) += bfin_mac.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 63b9ba0cc67e..c73be2848319 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -1251,6 +1251,12 @@ static void atl1_free_ring_resources(struct atl1_adapter *adapter) rrd_ring->desc = NULL; rrd_ring->dma = 0; + + adapter->cmb.dma = 0; + adapter->cmb.cmb = NULL; + + adapter->smb.dma = 0; + adapter->smb.smb = NULL; } static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) @@ -2847,10 +2853,11 @@ static int atl1_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); atl1_reset_hw(&adapter->hw); - adapter->cmb.cmb->int_stats = 0; - if (netif_running(netdev)) + if (netif_running(netdev)) { + adapter->cmb.cmb->int_stats = 0; atl1_up(adapter); + } netif_device_attach(netdev); return 0; diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 37617abc1647..efeffdf9e5fa 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -848,6 +848,15 @@ static int b44_poll(struct napi_struct *napi, int budget) b44_tx(bp); /* spin_unlock(&bp->tx_lock); */ } + if (bp->istat & ISTAT_RFO) { /* fast recovery, in ~20msec */ + bp->istat &= ~ISTAT_RFO; + b44_disable_ints(bp); + ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */ + b44_init_rings(bp); + b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY); + netif_wake_queue(bp->dev); + } + spin_unlock_irqrestore(&bp->lock, flags); work_done = 0; @@ -2161,8 +2170,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev, dev->irq = sdev->irq; SET_ETHTOOL_OPS(dev, &b44_ethtool_ops); - netif_carrier_off(dev); - err = ssb_bus_powerup(sdev->bus, 0); if (err) { dev_err(sdev->dev, @@ -2204,6 +2211,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev, goto err_out_powerdown; } + netif_carrier_off(dev); + ssb_set_drvdata(sdev, dev); /* Chip reset provides power to the b44 MAC & PCI cores, which diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 99197bd54da5..53306bf3f401 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -181,6 +181,7 @@ struct be_drvr_stats { u64 be_rx_bytes_prev; u64 be_rx_pkts; u32 be_rx_rate; + u32 be_rx_mcast_pkt; /* number of non ether type II frames dropped where * frame len > length field of Mac Hdr */ u32 be_802_3_dropped_frames; diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 3d305494a606..34abcc9403d6 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -140,10 +140,8 @@ int be_process_mcc(struct be_adapter *adapter, int *status) while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { /* Interpret flags as an async trailer */ - BUG_ON(!is_link_state_evt(compl->flags)); - - /* Interpret compl as a async link evt */ - be_async_link_state_process(adapter, + if (is_link_state_evt(compl->flags)) + be_async_link_state_process(adapter, (struct be_async_event_link_state *) compl); } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { *status = be_mcc_compl_process(adapter, compl); @@ -207,7 +205,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (msecs > 4000) { dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); - be_dump_ue(adapter); + be_detect_dump_ue(adapter); return -1; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index bdc10a28cfda..ad1e6fac60c5 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -992,5 +992,5 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, extern int be_cmd_get_phy_info(struct be_adapter *adapter, struct be_dma_mem *cmd); extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); -extern void be_dump_ue(struct be_adapter *adapter); +extern void be_detect_dump_ue(struct be_adapter *adapter); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c index cd16243c7c36..13f0abbc5205 100644 --- a/drivers/net/benet/be_ethtool.c +++ b/drivers/net/benet/be_ethtool.c @@ -60,6 +60,7 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(be_rx_events)}, {DRVSTAT_INFO(be_tx_compl)}, {DRVSTAT_INFO(be_rx_compl)}, + {DRVSTAT_INFO(be_rx_mcast_pkt)}, {DRVSTAT_INFO(be_ethrx_post_fail)}, {DRVSTAT_INFO(be_802_3_dropped_frames)}, {DRVSTAT_INFO(be_802_3_malformed_frames)}, diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 5d38046402b2..a2ec5df0d733 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -167,8 +167,11 @@ #define FLASH_FCoE_BIOS_START_g3 (13631488) #define FLASH_REDBOOT_START_g3 (262144) - - +/************* Rx Packet Type Encoding **************/ +#define BE_UNICAST_PACKET 0 +#define BE_MULTICAST_PACKET 1 +#define BE_BROADCAST_PACKET 2 +#define BE_RSVD_PACKET 3 /* * BE descriptors: host memory data structures whose formats diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 74e146f470c6..6eda7a022256 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -247,6 +247,7 @@ void netdev_stats_update(struct be_adapter *adapter) dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; + dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt; /* bad pkts received */ dev_stats->rx_errors = port_stats->rx_crc_errors + @@ -294,7 +295,6 @@ void netdev_stats_update(struct be_adapter *adapter) /* no space available in linux */ dev_stats->tx_dropped = 0; - dev_stats->multicast = port_stats->rx_multicast_frames; dev_stats->collisions = 0; /* detailed tx_errors */ @@ -848,7 +848,7 @@ static void be_rx_rate_update(struct be_adapter *adapter) } static void be_rx_stats_update(struct be_adapter *adapter, - u32 pktsize, u16 numfrags) + u32 pktsize, u16 numfrags, u8 pkt_type) { struct be_drvr_stats *stats = drvr_stats(adapter); @@ -856,6 +856,9 @@ static void be_rx_stats_update(struct be_adapter *adapter, stats->be_rx_frags += numfrags; stats->be_rx_bytes += pktsize; stats->be_rx_pkts++; + + if (pkt_type == BE_MULTICAST_PACKET) + stats->be_rx_mcast_pkt++; } static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) @@ -925,9 +928,11 @@ static void skb_fill_rx_data(struct be_adapter *adapter, u16 rxq_idx, i, j; u32 pktsize, hdr_len, curr_frag_len, size; u8 *start; + u8 pkt_type; rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp); page_info = get_rx_page_info(adapter, rxq_idx); @@ -993,7 +998,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, BUG_ON(j > MAX_SKB_FRAGS); done: - be_rx_stats_update(adapter, pktsize, num_rcvd); + be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type); } /* Process the RX completion indicated by rxcp when GRO is disabled */ @@ -1060,6 +1065,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; u16 i, rxq_idx = 0, vid, j; u8 vtm; + u8 pkt_type; num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); /* Is it a flush compl that has no data */ @@ -1070,6 +1076,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); + pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp); /* vlanf could be wrongly set in some cards. * ignore if vtm is not set */ @@ -1125,7 +1132,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); } - be_rx_stats_update(adapter, pkt_size, num_rcvd); + be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type); } static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) @@ -1743,26 +1750,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget) return 1; } -static inline bool be_detect_ue(struct be_adapter *adapter) -{ - u32 online0 = 0, online1 = 0; - - pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0); - - pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1); - - if (!online0 || !online1) { - adapter->ue_detected = true; - dev_err(&adapter->pdev->dev, - "UE Detected!! online0=%d online1=%d\n", - online0, online1); - return true; - } - - return false; -} - -void be_dump_ue(struct be_adapter *adapter) +void be_detect_dump_ue(struct be_adapter *adapter) { u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask; u32 i; @@ -1779,6 +1767,11 @@ void be_dump_ue(struct be_adapter *adapter) ue_status_lo = (ue_status_lo & (~ue_status_lo_mask)); ue_status_hi = (ue_status_hi & (~ue_status_hi_mask)); + if (ue_status_lo || ue_status_hi) { + adapter->ue_detected = true; + dev_err(&adapter->pdev->dev, "UE Detected!!\n"); + } + if (ue_status_lo) { for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) { if (ue_status_lo & 1) @@ -1814,10 +1807,8 @@ static void be_worker(struct work_struct *work) adapter->rx_post_starved = false; be_post_rx_frags(adapter); } - if (!adapter->ue_detected) { - if (be_detect_ue(adapter)) - be_dump_ue(adapter); - } + if (!adapter->ue_detected) + be_detect_dump_ue(adapter); schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); } diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h index 53af9c93e75c..0c2d96ed561c 100644 --- a/drivers/net/bnx2x/bnx2x.h +++ b/drivers/net/bnx2x/bnx2x.h @@ -20,8 +20,8 @@ * (you will need to reboot afterwards) */ /* #define BNX2X_STOP_ON_ERROR */ -#define DRV_MODULE_VERSION "1.52.53-3" -#define DRV_MODULE_RELDATE "2010/18/04" +#define DRV_MODULE_VERSION "1.52.53-4" +#define DRV_MODULE_RELDATE "2010/16/08" #define BNX2X_BC_VER 0x040200 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index b4ec2b02a465..f8c3f08e4ce7 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -4328,10 +4328,12 @@ static int bnx2x_init_port(struct bnx2x *bp) val |= aeu_gpio_mask; REG_WR(bp, offset, val); } + bp->port.need_hw_lock = 1; break; - case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727: + bp->port.need_hw_lock = 1; + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: /* add SPIO 5 to group 0 */ { u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 : @@ -4341,7 +4343,10 @@ static int bnx2x_init_port(struct bnx2x *bp) REG_WR(bp, reg_addr, val); } break; - + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: + case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: + bp->port.need_hw_lock = 1; + break; default: break; } diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 822f586d72af..0ddf4c66afe2 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2466,6 +2466,9 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) + goto out; + read_lock(&bond->lock); slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), orig_dev); diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index c746b331771d..26bb118c4533 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -362,6 +362,9 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) + goto out; + if (skb->len < sizeof(struct arp_pkt)) { pr_debug("Packet is too small to be an ARP\n"); goto out; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2cc4cfc31892..e953c6ad6e6d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2797,9 +2797,15 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * so it can wait */ bond_for_each_slave(bond, slave, i) { + unsigned long trans_start = dev_trans_start(slave->dev); + if (slave->link != BOND_LINK_UP) { - if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) && - time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) { + if (time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + delta_in_ticks) && + time_in_range(jiffies, + slave->dev->last_rx - delta_in_ticks, + slave->dev->last_rx + delta_in_ticks)) { slave->link = BOND_LINK_UP; slave->state = BOND_STATE_ACTIVE; @@ -2827,8 +2833,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work) * when the source ip is 0, so don't take the link down * if we don't know our ip yet */ - if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) || - (time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) { + if (!time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + 2 * delta_in_ticks) || + !time_in_range(jiffies, + slave->dev->last_rx - delta_in_ticks, + slave->dev->last_rx + 2 * delta_in_ticks)) { slave->link = BOND_LINK_DOWN; slave->state = BOND_STATE_BACKUP; @@ -2883,13 +2893,16 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) { struct slave *slave; int i, commit = 0; + unsigned long trans_start; bond_for_each_slave(bond, slave, i) { slave->new_link = BOND_LINK_NOCHANGE; if (slave->link != BOND_LINK_UP) { - if (time_before_eq(jiffies, slave_last_rx(bond, slave) + - delta_in_ticks)) { + if (time_in_range(jiffies, + slave_last_rx(bond, slave) - delta_in_ticks, + slave_last_rx(bond, slave) + delta_in_ticks)) { + slave->new_link = BOND_LINK_UP; commit++; } @@ -2902,8 +2915,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) * active. This avoids bouncing, as the last receive * times need a full ARP monitor cycle to be updated. */ - if (!time_after_eq(jiffies, slave->jiffies + - 2 * delta_in_ticks)) + if (time_in_range(jiffies, + slave->jiffies - delta_in_ticks, + slave->jiffies + 2 * delta_in_ticks)) continue; /* @@ -2921,8 +2935,10 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) */ if (slave->state == BOND_STATE_BACKUP && !bond->current_arp_slave && - time_after(jiffies, slave_last_rx(bond, slave) + - 3 * delta_in_ticks)) { + !time_in_range(jiffies, + slave_last_rx(bond, slave) - delta_in_ticks, + slave_last_rx(bond, slave) + 3 * delta_in_ticks)) { + slave->new_link = BOND_LINK_DOWN; commit++; } @@ -2933,11 +2949,15 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks) * - (more than 2*delta since receive AND * the bond has an IP address) */ + trans_start = dev_trans_start(slave->dev); if ((slave->state == BOND_STATE_ACTIVE) && - (time_after_eq(jiffies, dev_trans_start(slave->dev) + - 2 * delta_in_ticks) || - (time_after_eq(jiffies, slave_last_rx(bond, slave) - + 2 * delta_in_ticks)))) { + (!time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + 2 * delta_in_ticks) || + !time_in_range(jiffies, + slave_last_rx(bond, slave) - delta_in_ticks, + slave_last_rx(bond, slave) + 2 * delta_in_ticks))) { + slave->new_link = BOND_LINK_DOWN; commit++; } @@ -2956,6 +2976,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) { struct slave *slave; int i; + unsigned long trans_start; bond_for_each_slave(bond, slave, i) { switch (slave->new_link) { @@ -2963,10 +2984,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks) continue; case BOND_LINK_UP: + trans_start = dev_trans_start(slave->dev); if ((!bond->curr_active_slave && - time_before_eq(jiffies, - dev_trans_start(slave->dev) + - delta_in_ticks)) || + time_in_range(jiffies, + trans_start - delta_in_ticks, + trans_start + delta_in_ticks)) || bond->curr_active_slave != slave) { slave->link = BOND_LINK_UP; bond->current_arp_slave = NULL; @@ -5142,6 +5164,15 @@ int bond_create(struct net *net, const char *name) res = dev_alloc_name(bond_dev, "bond%d"); if (res < 0) goto out; + } else { + /* + * If we're given a name to register + * we need to ensure that its not already + * registered + */ + res = -EEXIST; + if (__dev_get_by_name(net, name) != NULL) + goto out; } res = register_netdevice(bond_dev); diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig index 631a6242b011..75bfc3a9d95f 100644 --- a/drivers/net/caif/Kconfig +++ b/drivers/net/caif/Kconfig @@ -15,7 +15,7 @@ config CAIF_TTY config CAIF_SPI_SLAVE tristate "CAIF SPI transport driver for slave interface" - depends on CAIF + depends on CAIF && HAS_DMA default n ---help--- The CAIF Link layer SPI Protocol driver for Slave SPI interface. diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index ad19585d960b..f208712c0b90 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2296,6 +2296,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) case CHELSIO_GET_QSET_NUM:{ struct ch_reg edata; + memset(&edata, 0, sizeof(struct ch_reg)); + edata.cmd = CHELSIO_GET_QSET_NUM; edata.val = pi->nqsets; if (copy_to_user(useraddr, &edata, sizeof(edata))) diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index a4a0d2b6eb1c..d3d4a57e2450 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -936,12 +936,14 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw) ew32(IMC, 0xffffffff); icr = er32(ICR); - /* Install any alternate MAC address into RAR0 */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; + if (hw->mac.type == e1000_82571) { + /* Install any alternate MAC address into RAR0 */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + return ret_val; - e1000e_set_laa_state_82571(hw, true); + e1000e_set_laa_state_82571(hw, true); + } /* Reinitialize the 82571 serdes link state machine */ if (hw->phy.media_type == e1000_media_type_internal_serdes) @@ -1618,14 +1620,16 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) { s32 ret_val = 0; - /* - * If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - goto out; + if (hw->mac.type == e1000_82571) { + /* + * If there's an alternate MAC address place it in RAR0 + * so that it will override the Si installed default perm + * address. + */ + ret_val = e1000_check_alt_mac_addr_generic(hw); + if (ret_val) + goto out; + } ret_val = e1000_read_mac_addr_generic(hw); @@ -1833,6 +1837,7 @@ struct e1000_info e1000_82573_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_SWSM_ON_LOAD, + .flags2 = FLAG2_DISABLE_ASPM_L1, .pba = 20, .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 307a72f483ee..93b3bedae8d2 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -621,6 +621,7 @@ #define E1000_FLASH_UPDATES 2000 /* NVM Word Offsets */ +#define NVM_COMPAT 0x0003 #define NVM_ID_LED_SETTINGS 0x0004 #define NVM_INIT_CONTROL2_REG 0x000F #define NVM_INIT_CONTROL3_PORT_B 0x0014 @@ -643,6 +644,9 @@ /* Mask bits for fields in Word 0x1a of the NVM */ #define NVM_WORD1A_ASPM_MASK 0x000C +/* Mask bits for fields in Word 0x03 of the EEPROM */ +#define NVM_COMPAT_LOM 0x0800 + /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ #define NVM_SUM 0xBABA diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 66ed08f726fb..ba302a5c2c30 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h @@ -57,6 +57,7 @@ enum e1e_registers { E1000_SCTL = 0x00024, /* SerDes Control - RW */ E1000_FCAL = 0x00028, /* Flow Control Address Low - RW */ E1000_FCAH = 0x0002C, /* Flow Control Address High -RW */ + E1000_FEXTNVM4 = 0x00024, /* Future Extended NVM 4 - RW */ E1000_FEXTNVM = 0x00028, /* Future Extended NVM - RW */ E1000_FCT = 0x00030, /* Flow Control Type - RW */ E1000_VET = 0x00038, /* VLAN Ether Type - RW */ diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 63930d12711c..57b5435599ab 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -105,6 +105,10 @@ #define E1000_FEXTNVM_SW_CONFIG 1 #define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* Bit redefined for ICH8M :/ */ +#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 +#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 +#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 + #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL #define E1000_ICH_RAR_ENTRIES 7 @@ -125,6 +129,7 @@ /* SMBus Address Phy Register */ #define HV_SMB_ADDR PHY_REG(768, 26) +#define HV_SMB_ADDR_MASK 0x007F #define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_VALID 0x0080 @@ -237,6 +242,8 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); +static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); +static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -272,7 +279,7 @@ static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) { struct e1000_phy_info *phy = &hw->phy; - u32 ctrl; + u32 ctrl, fwsm; s32 ret_val = 0; phy->addr = 1; @@ -294,7 +301,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) * disabled, then toggle the LANPHYPC Value bit to force * the interconnect to PCIe mode. */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { + fwsm = er32(FWSM); + if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) { ctrl = er32(CTRL); ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; @@ -303,6 +311,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; ew32(CTRL, ctrl); msleep(50); + + /* + * Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if (hw->mac.type == e1000_pch2lan) + e1000_gate_hw_phy_config_ich8lan(hw, true); } /* @@ -315,6 +330,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) if (ret_val) goto out; + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(fwsm & E1000_ICH_FWSM_FW_VALID)) { + msleep(10); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + phy->id = e1000_phy_unknown; ret_val = e1000e_get_phy_id(hw); if (ret_val) @@ -561,13 +583,10 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) if (mac->type == e1000_ich8lan) e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - /* Disable PHY configuration by hardware, config by software */ - if (mac->type == e1000_pch2lan) { - u32 extcnf_ctrl = er32(EXTCNF_CTRL); - - extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - } + /* Gate automatic PHY configuration by hardware on managed 82579 */ + if ((mac->type == e1000_pch2lan) && + (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); return 0; } @@ -652,6 +671,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) goto out; } + if (hw->mac.type == e1000_pch2lan) { + ret_val = e1000_k1_workaround_lv(hw); + if (ret_val) + goto out; + } + /* * Check if there was DownShift, must be checked * immediately after link-up @@ -895,6 +920,34 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) } /** + * e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states + * @hw: pointer to the HW structure + * + * Assumes semaphore already acquired. + * + **/ +static s32 e1000_write_smbus_addr(struct e1000_hw *hw) +{ + u16 phy_data; + u32 strap = er32(STRAP); + s32 ret_val = 0; + + strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; + + ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); + if (ret_val) + goto out; + + phy_data &= ~HV_SMB_ADDR_MASK; + phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); + phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; + ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); + +out: + return ret_val; +} + +/** * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration * @hw: pointer to the HW structure * @@ -903,7 +956,6 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) **/ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) { - struct e1000_adapter *adapter = hw->adapter; struct e1000_phy_info *phy = &hw->phy; u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; s32 ret_val = 0; @@ -921,7 +973,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) if (phy->type != e1000_phy_igp_3) return ret_val; - if (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) { + if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) || + (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) { sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; break; } @@ -961,21 +1014,16 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && - ((hw->mac.type == e1000_pchlan) || - (hw->mac.type == e1000_pch2lan))) { + if ((!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && + (hw->mac.type == e1000_pchlan)) || + (hw->mac.type == e1000_pch2lan)) { /* * HW configures the SMBus address and LEDs when the * OEM and LCD Write Enable bits are set in the NVM. * When both NVM bits are cleared, SW will configure * them instead. */ - data = er32(STRAP); - data &= E1000_STRAP_SMBUS_ADDRESS_MASK; - reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT; - reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, - reg_data); + ret_val = e1000_write_smbus_addr(hw); if (ret_val) goto out; @@ -1440,10 +1488,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; /* Enable jumbo frame workaround in the PHY */ - e1e_rphy(hw, PHY_REG(769, 20), &data); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); - if (ret_val) - goto out; e1e_rphy(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); data |= (0x37 << 5); @@ -1452,7 +1496,6 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; e1e_rphy(hw, PHY_REG(769, 16), &data); data &= ~(1 << 13); - data |= (1 << 12); ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); if (ret_val) goto out; @@ -1477,7 +1520,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) mac_reg = er32(RCTL); mac_reg &= ~E1000_RCTL_SECRC; - ew32(FFLT_DBG, mac_reg); + ew32(RCTL, mac_reg); ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_CTRL_OFFSET, @@ -1503,17 +1546,12 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) goto out; /* Write PHY register values back to h/w defaults */ - e1e_rphy(hw, PHY_REG(769, 20), &data); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14)); - if (ret_val) - goto out; e1e_rphy(hw, PHY_REG(769, 23), &data); data &= ~(0x7F << 5); ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); if (ret_val) goto out; e1e_rphy(hw, PHY_REG(769, 16), &data); - data &= ~(1 << 12); data |= (1 << 13); ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); if (ret_val) @@ -1559,6 +1597,69 @@ out: } /** + * e1000_k1_gig_workaround_lv - K1 Si workaround + * @hw: pointer to the HW structure + * + * Workaround to set the K1 beacon duration for 82579 parts + **/ +static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) +{ + s32 ret_val = 0; + u16 status_reg = 0; + u32 mac_reg; + + if (hw->mac.type != e1000_pch2lan) + goto out; + + /* Set K1 beacon duration based on 1Gbps speed or otherwise */ + ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); + if (ret_val) + goto out; + + if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) + == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { + mac_reg = er32(FEXTNVM4); + mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; + + if (status_reg & HV_M_STATUS_SPEED_1000) + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; + else + mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; + + ew32(FEXTNVM4, mac_reg); + } + +out: + return ret_val; +} + +/** + * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware + * @hw: pointer to the HW structure + * @gate: boolean set to true to gate, false to ungate + * + * Gate/ungate the automatic PHY configuration via hardware; perform + * the configuration via software instead. + **/ +static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) +{ + u32 extcnf_ctrl; + + if (hw->mac.type != e1000_pch2lan) + return; + + extcnf_ctrl = er32(EXTCNF_CTRL); + + if (gate) + extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; + else + extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; + + ew32(EXTCNF_CTRL, extcnf_ctrl); + return; +} + +/** * e1000_lan_init_done_ich8lan - Check for PHY config completion * @hw: pointer to the HW structure * @@ -1602,6 +1703,9 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) if (e1000_check_reset_block(hw)) goto out; + /* Allow time for h/w to get to quiescent state after reset */ + msleep(10); + /* Perform any necessary post-reset workarounds */ switch (hw->mac.type) { case e1000_pchlan: @@ -1630,6 +1734,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) /* Configure the LCD with the OEM bits in NVM */ ret_val = e1000_oem_bits_config_ich8lan(hw, true); + /* Ungate automatic PHY configuration on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { + msleep(10); + e1000_gate_hw_phy_config_ich8lan(hw, false); + } + out: return ret_val; } @@ -1646,6 +1757,11 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) { s32 ret_val = 0; + /* Gate automatic PHY configuration by hardware on non-managed 82579 */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); + ret_val = e1000e_phy_hw_reset_generic(hw); if (ret_val) goto out; @@ -2910,6 +3026,14 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) * external PHY is reset. */ ctrl |= E1000_CTRL_PHY_RST; + + /* + * Gate automatic PHY configuration by hardware on + * non-managed 82579 + */ + if ((hw->mac.type == e1000_pch2lan) && + !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) + e1000_gate_hw_phy_config_ich8lan(hw, true); } ret_val = e1000_acquire_swflag_ich8lan(hw); e_dbg("Issuing a global reset to ich8lan\n"); @@ -3460,13 +3584,20 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw) { u32 phy_ctrl; + s32 ret_val; phy_ctrl = er32(PHY_CTRL); phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE; ew32(PHY_CTRL, phy_ctrl); - if (hw->mac.type >= e1000_pchlan) - e1000_phy_hw_reset_ich8lan(hw); + if (hw->mac.type >= e1000_pchlan) { + e1000_oem_bits_config_ich8lan(hw, true); + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + return; + e1000_write_smbus_addr(hw); + hw->phy.ops.release(hw); + } } /** diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c index df4a27922931..0fd4eb5ac5fb 100644 --- a/drivers/net/e1000e/lib.c +++ b/drivers/net/e1000e/lib.c @@ -183,6 +183,16 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) u16 offset, nvm_alt_mac_addr_offset, nvm_data; u8 alt_mac_addr[ETH_ALEN]; + ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); + if (ret_val) + goto out; + + /* Check for LOM (vs. NIC) or one of two valid mezzanine cards */ + if (!((nvm_data & NVM_COMPAT_LOM) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) || + (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD))) + goto out; + ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, &nvm_alt_mac_addr_offset); if (ret_val) { diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2b8ef44bd2b1..e561d15c3eb1 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2704,6 +2704,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) u32 psrctl = 0; u32 pages = 0; + /* Workaround Si errata on 82579 - configure jumbo frame flow */ + if (hw->mac.type == e1000_pch2lan) { + s32 ret_val; + + if (adapter->netdev->mtu > ETH_DATA_LEN) + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); + else + ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); + } + /* Program MC offset vector base */ rctl = er32(RCTL); rctl &= ~(3 << E1000_RCTL_MO_SHIFT); @@ -2744,16 +2754,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) e1e_wphy(hw, 22, phy_data); } - /* Workaround Si errata on 82579 - configure jumbo frame flow */ - if (hw->mac.type == e1000_pch2lan) { - s32 ret_val; - - if (rctl & E1000_RCTL_LPE) - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); - else - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); - } - /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; rctl |= E1000_RCTL_BSEX; @@ -4833,6 +4833,15 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } + /* Jumbo frame workaround on 82579 requires CRC be stripped */ + if ((adapter->hw.mac.type == e1000_pch2lan) && + !(adapter->flags2 & FLAG2_CRC_STRIPPING) && + (new_mtu > ETH_DATA_LEN)) { + e_err("Jumbo Frames not supported on 82579 when CRC " + "stripping is disabled.\n"); + return -EINVAL; + } + /* 82573 Errata 17 */ if (((adapter->hw.mac.type == e1000_82573) || (adapter->hw.mac.type == e1000_82574)) && diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 99a929964e3c..1846623c6ae6 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include <asm/io.h> #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0105" +#define DRV_VERSION "EHEA_0106" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 @@ -400,6 +400,7 @@ struct ehea_port_res { u32 poll_counter; struct net_lro_mgr lro_mgr; struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS]; + int sq_restart_flag; }; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 897719b49f96..6372610ed240 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -533,8 +533,15 @@ static inline void ehea_fill_skb(struct net_device *dev, int length = cqe->num_bytes_transfered - 4; /*remove CRC */ skb_put(skb, length); - skb->ip_summed = CHECKSUM_UNNECESSARY; skb->protocol = eth_type_trans(skb, dev); + + /* The packet was not an IPV4 packet so a complemented checksum was + calculated. The value is found in the Internet Checksum field. */ + if (cqe->status & EHEA_CQE_BLIND_CKSUM) { + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = csum_unfold(~cqe->inet_checksum_value); + } else + skb->ip_summed = CHECKSUM_UNNECESSARY; } static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array, @@ -776,6 +783,53 @@ static int ehea_proc_rwqes(struct net_device *dev, return processed; } +#define SWQE_RESTART_CHECK 0xdeadbeaff00d0000ull + +static void reset_sq_restart_flag(struct ehea_port *port) +{ + int i; + + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { + struct ehea_port_res *pr = &port->port_res[i]; + pr->sq_restart_flag = 0; + } +} + +static void check_sqs(struct ehea_port *port) +{ + struct ehea_swqe *swqe; + int swqe_index; + int i, k; + + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { + struct ehea_port_res *pr = &port->port_res[i]; + k = 0; + swqe = ehea_get_swqe(pr->qp, &swqe_index); + memset(swqe, 0, SWQE_HEADER_SIZE); + atomic_dec(&pr->swqe_avail); + + swqe->tx_control |= EHEA_SWQE_PURGE; + swqe->wr_id = SWQE_RESTART_CHECK; + swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION; + swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT; + swqe->immediate_data_length = 80; + + ehea_post_swqe(pr->qp, swqe); + + while (pr->sq_restart_flag == 0) { + msleep(5); + if (++k == 100) { + ehea_error("HW/SW queues out of sync"); + ehea_schedule_port_reset(pr->port); + return; + } + } + } + + return; +} + + static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) { struct sk_buff *skb; @@ -793,6 +847,13 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) cqe_counter++; rmb(); + + if (cqe->wr_id == SWQE_RESTART_CHECK) { + pr->sq_restart_flag = 1; + swqe_av++; + break; + } + if (cqe->status & EHEA_CQE_STAT_ERR_MASK) { ehea_error("Bad send completion status=0x%04X", cqe->status); @@ -2675,8 +2736,10 @@ static void ehea_flush_sq(struct ehea_port *port) int k = 0; while (atomic_read(&pr->swqe_avail) < swqe_max) { msleep(5); - if (++k == 20) + if (++k == 20) { + ehea_error("WARNING: sq not flushed completely"); break; + } } } } @@ -2917,6 +2980,7 @@ static void ehea_rereg_mrs(struct work_struct *work) port_napi_disable(port); mutex_unlock(&port->port_lock); } + reset_sq_restart_flag(port); } /* Unregister old memory region */ @@ -2951,6 +3015,7 @@ static void ehea_rereg_mrs(struct work_struct *work) mutex_lock(&port->port_lock); port_napi_enable(port); ret = ehea_restart_qps(dev); + check_sqs(port); if (!ret) netif_wake_queue(dev); mutex_unlock(&port->port_lock); diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index f608a6c54af5..38104734a3be 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -150,6 +150,7 @@ struct ehea_rwqe { #define EHEA_CQE_TYPE_RQ 0x60 #define EHEA_CQE_STAT_ERR_MASK 0x700F #define EHEA_CQE_STAT_FAT_ERR_MASK 0xF +#define EHEA_CQE_BLIND_CKSUM 0x8000 #define EHEA_CQE_STAT_ERR_TCP 0x4000 #define EHEA_CQE_STAT_ERR_IP 0x2000 #define EHEA_CQE_STAT_ERR_CRC 0x1000 diff --git a/drivers/net/eql.c b/drivers/net/eql.c index dda2c7944da9..0cb1cf9cf4b0 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c @@ -555,6 +555,8 @@ static int eql_g_master_cfg(struct net_device *dev, master_config_t __user *mcp) equalizer_t *eql; master_config_t mc; + memset(&mc, 0, sizeof(master_config_t)); + if (eql_is_master(dev)) { eql = netdev_priv(dev); mc.max_slaves = eql->max_slaves; diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 768b840aeb6b..cce32d43175f 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -678,24 +678,37 @@ static int fec_enet_mii_probe(struct net_device *dev) { struct fec_enet_private *fep = netdev_priv(dev); struct phy_device *phy_dev = NULL; - int ret; + char mdio_bus_id[MII_BUS_ID_SIZE]; + char phy_name[MII_BUS_ID_SIZE + 3]; + int phy_id; fep->phy_dev = NULL; - /* find the first phy */ - phy_dev = phy_find_first(fep->mii_bus); - if (!phy_dev) { - printk(KERN_ERR "%s: no PHY found\n", dev->name); - return -ENODEV; + /* check for attached phy */ + for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) { + if ((fep->mii_bus->phy_mask & (1 << phy_id))) + continue; + if (fep->mii_bus->phy_map[phy_id] == NULL) + continue; + if (fep->mii_bus->phy_map[phy_id]->phy_id == 0) + continue; + strncpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE); + break; } - /* attach the mac to the phy */ - ret = phy_connect_direct(dev, phy_dev, - &fec_enet_adjust_link, 0, - PHY_INTERFACE_MODE_MII); - if (ret) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return ret; + if (phy_id >= PHY_MAX_ADDR) { + printk(KERN_INFO "%s: no PHY, assuming direct connection " + "to switch\n", dev->name); + strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); + phy_id = 0; + } + + snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); + phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0, + PHY_INTERFACE_MODE_MII); + if (IS_ERR(phy_dev)) { + printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); + return PTR_ERR(phy_dev); } /* mask with MAC supported features */ @@ -738,7 +751,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id); + snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1); fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; @@ -1311,6 +1324,9 @@ fec_probe(struct platform_device *pdev) if (ret) goto failed_mii_init; + /* Carrier starts down, phylib will bring it up */ + netif_carrier_off(ndev); + ret = register_netdev(ndev); if (ret) goto failed_register; diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 3506fd6ad726..519e19e23955 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2928,7 +2928,7 @@ static int __devinit emac_probe(struct platform_device *ofdev, if (dev->emac_irq != NO_IRQ) irq_dispose_mapping(dev->emac_irq); err_free: - kfree(ndev); + free_netdev(ndev); err_gone: /* if we were on the bootlist, remove us as we won't show up and * wake up all waiters to notify them in case they were waiting @@ -2971,7 +2971,7 @@ static int __devexit emac_remove(struct platform_device *ofdev) if (dev->emac_irq != NO_IRQ) irq_dispose_mapping(dev->emac_irq); - kfree(dev->ndev); + free_netdev(dev->ndev); return 0; } diff --git a/drivers/net/ibm_newemac/debug.c b/drivers/net/ibm_newemac/debug.c index 3995fafc1e08..8c6c1e2a8750 100644 --- a/drivers/net/ibm_newemac/debug.c +++ b/drivers/net/ibm_newemac/debug.c @@ -238,7 +238,7 @@ void emac_dbg_dump_all(void) } #if defined(CONFIG_MAGIC_SYSRQ) -static void emac_sysrq_handler(int key, struct tty_struct *tty) +static void emac_sysrq_handler(int key) { emac_dbg_dump_all(); } diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2602852cc55a..4734c939ad03 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -1113,7 +1113,8 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) struct ibmveth_adapter *adapter = netdev_priv(dev); struct vio_dev *viodev = adapter->vdev; int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH; - int i; + int i, rc; + int need_restart = 0; if (new_mtu < IBMVETH_MAX_MTU) return -EINVAL; @@ -1127,35 +1128,32 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) /* Deactivate all the buffer pools so that the next loop can activate only the buffer pools necessary to hold the new MTU */ - for (i = 0; i < IbmVethNumBufferPools; i++) - if (adapter->rx_buff_pool[i].active) { - ibmveth_free_buffer_pool(adapter, - &adapter->rx_buff_pool[i]); - adapter->rx_buff_pool[i].active = 0; - } + if (netif_running(adapter->netdev)) { + need_restart = 1; + adapter->pool_config = 1; + ibmveth_close(adapter->netdev); + adapter->pool_config = 0; + } /* Look for an active buffer pool that can hold the new MTU */ for(i = 0; i<IbmVethNumBufferPools; i++) { adapter->rx_buff_pool[i].active = 1; if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) { - if (netif_running(adapter->netdev)) { - adapter->pool_config = 1; - ibmveth_close(adapter->netdev); - adapter->pool_config = 0; - dev->mtu = new_mtu; - vio_cmo_set_dev_desired(viodev, - ibmveth_get_desired_dma - (viodev)); - return ibmveth_open(adapter->netdev); - } dev->mtu = new_mtu; vio_cmo_set_dev_desired(viodev, ibmveth_get_desired_dma (viodev)); + if (need_restart) { + return ibmveth_open(adapter->netdev); + } return 0; } } + + if (need_restart && (rc = ibmveth_open(adapter->netdev))) + return rc; + return -EINVAL; } diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c index b4fb07a6f13f..51919fcd50c2 100644 --- a/drivers/net/ks8851.c +++ b/drivers/net/ks8851.c @@ -503,30 +503,33 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE); - if (rxlen > 0) { - skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8); - if (!skb) { - /* todo - dump frame and move on */ - } + if (rxlen > 4) { + unsigned int rxalign; + + rxlen -= 4; + rxalign = ALIGN(rxlen, 4); + skb = netdev_alloc_skb_ip_align(ks->netdev, rxalign); + if (skb) { - /* two bytes to ensure ip is aligned, and four bytes - * for the status header and 4 bytes of garbage */ - skb_reserve(skb, 2 + 4 + 4); + /* 4 bytes of status header + 4 bytes of + * garbage: we put them before ethernet + * header, so that they are copied, + * but ignored. + */ - rxpkt = skb_put(skb, rxlen - 4) - 8; + rxpkt = skb_put(skb, rxlen) - 8; - /* align the packet length to 4 bytes, and add 4 bytes - * as we're getting the rx status header as well */ - ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8); + ks8851_rdfifo(ks, rxpkt, rxalign + 8); - if (netif_msg_pktdata(ks)) - ks8851_dbg_dumpkkt(ks, rxpkt); + if (netif_msg_pktdata(ks)) + ks8851_dbg_dumpkkt(ks, rxpkt); - skb->protocol = eth_type_trans(skb, ks->netdev); - netif_rx(skb); + skb->protocol = eth_type_trans(skb, ks->netdev); + netif_rx(skb); - ks->netdev->stats.rx_packets++; - ks->netdev->stats.rx_bytes += rxlen - 4; + ks->netdev->stats.rx_packets++; + ks->netdev->stats.rx_bytes += rxlen; + } } ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr); diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index c7b624711f5e..87f0a93b165c 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c @@ -38,6 +38,7 @@ #include <linux/of_device.h> #include <linux/of_mdio.h> #include <linux/of_platform.h> +#include <linux/of_address.h> #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/tcp.h> /* needed for sizeof(tcphdr) */ @@ -902,8 +903,8 @@ temac_poll_controller(struct net_device *ndev) disable_irq(lp->tx_irq); disable_irq(lp->rx_irq); - ll_temac_rx_irq(lp->tx_irq, lp); - ll_temac_tx_irq(lp->rx_irq, lp); + ll_temac_rx_irq(lp->tx_irq, ndev); + ll_temac_tx_irq(lp->rx_irq, ndev); enable_irq(lp->tx_irq); enable_irq(lp->rx_irq); diff --git a/drivers/net/ll_temac_mdio.c b/drivers/net/ll_temac_mdio.c index 5ae28c975b38..8cf9d4f56bb2 100644 --- a/drivers/net/ll_temac_mdio.c +++ b/drivers/net/ll_temac_mdio.c @@ -10,6 +10,7 @@ #include <linux/phy.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/of_address.h> #include <linux/slab.h> #include <linux/of_mdio.h> diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index ffa1b9ce1cc5..6dca3574e355 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -53,8 +53,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 73 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.73" +#define _NETXEN_NIC_LINUX_SUBVERSION 74 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.74" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index c865dda2adf1..b075a35b85d4 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1540,7 +1540,6 @@ netxen_process_rcv(struct netxen_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1602,8 +1601,6 @@ netxen_process_lro(struct netxen_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); @@ -1805,8 +1802,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, netxen_ctx_msg msg = 0; struct list_head *head; - spin_lock(&rds_ring->lock); - producer = rds_ring->producer; head = &rds_ring->free_list; @@ -1853,8 +1848,6 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, NETXEN_RCV_PRODUCER_OFFSET), msg); } } - - spin_unlock(&rds_ring->lock); } static void diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index fd86e18604e6..73d314592230 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -2032,8 +2032,6 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) struct netxen_adapter *adapter = netdev_priv(netdev); struct net_device_stats *stats = &netdev->stats; - memset(stats, 0, sizeof(*stats)); - stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes; @@ -2133,9 +2131,16 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) #ifdef CONFIG_NET_POLL_CONTROLLER static void netxen_nic_poll_controller(struct net_device *netdev) { + int ring; + struct nx_host_sds_ring *sds_ring; struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + disable_irq(adapter->irq); - netxen_intr(adapter->irq, adapter); + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netxen_intr(adapter->irq, sds_ring); + } enable_irq(adapter->irq); } #endif diff --git a/drivers/net/niu.c b/drivers/net/niu.c index bc695d53cdcc..fe6983af6918 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -7269,32 +7269,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np, struct niu_parent *parent = np->parent; struct niu_tcam_entry *tp; int i, idx, cnt; - u16 n_entries; unsigned long flags; - + int ret = 0; /* put the tcam size here */ nfc->data = tcam_get_size(np); niu_lock_parent(np, flags); - n_entries = nfc->rule_cnt; for (cnt = 0, i = 0; i < nfc->data; i++) { idx = tcam_get_index(np, i); tp = &parent->tcam[idx]; if (!tp->valid) continue; + if (cnt == nfc->rule_cnt) { + ret = -EMSGSIZE; + break; + } rule_locs[cnt] = i; cnt++; } niu_unlock_parent(np, flags); - if (n_entries != cnt) { - /* print warning, this should not happen */ - netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n", - np->parent->index, __func__, n_entries, cnt); - } - - return 0; + return ret; } static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index c3edfe4c2651..f9b509a6b09a 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - int *has_shmem = priv_data; + int *priv = priv_data; + int try = (*priv & 0x1); int i; cistpl_io_t *io = &cfg->io; @@ -525,77 +526,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev, i = p_dev->resource[1]->end = 0; } - *has_shmem = ((cfg->mem.nwin == 1) && - (cfg->mem.win[0].len >= 0x4000)); + *priv &= ((cfg->mem.nwin == 1) && + (cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10; + p_dev->resource[0]->start = io->win[i].base; p_dev->resource[0]->end = io->win[i].len; - p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + if (!try) + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + else + p_dev->io_lines = 16; if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32) return try_io_port(p_dev); - return 0; + return -EINVAL; +} + +static hw_info_t *pcnet_try_config(struct pcmcia_device *link, + int *has_shmem, int try) +{ + struct net_device *dev = link->priv; + hw_info_t *local_hw_info; + pcnet_dev_t *info = PRIV(dev); + int priv = try; + int ret; + + ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); + if (ret) { + dev_warn(&link->dev, "no useable port range found\n"); + return NULL; + } + *has_shmem = (priv & 0x10); + + if (!link->irq) + return NULL; + + if (resource_size(link->resource[1]) == 8) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + if ((link->manf_id == MANFID_IBM) && + (link->card_id == PRODID_IBM_HOME_AND_AWAY)) + link->conf.ConfigIndex |= 0x10; + + ret = pcmcia_request_configuration(link, &link->conf); + if (ret) + return NULL; + + dev->irq = link->irq; + dev->base_addr = link->resource[0]->start; + + if (info->flags & HAS_MISC_REG) { + if ((if_port == 1) || (if_port == 2)) + dev->if_port = if_port; + else + dev_notice(&link->dev, "invalid if_port requested\n"); + } else + dev->if_port = 0; + + if ((link->conf.ConfigBase == 0x03c0) && + (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { + dev_info(&link->dev, + "this is an AX88190 card - use axnet_cs instead.\n"); + return NULL; + } + + local_hw_info = get_hwinfo(link); + if (!local_hw_info) + local_hw_info = get_prom(link); + if (!local_hw_info) + local_hw_info = get_dl10019(link); + if (!local_hw_info) + local_hw_info = get_ax88190(link); + if (!local_hw_info) + local_hw_info = get_hwired(link); + + return local_hw_info; } static int pcnet_config(struct pcmcia_device *link) { struct net_device *dev = link->priv; pcnet_dev_t *info = PRIV(dev); - int ret, start_pg, stop_pg, cm_offset; + int start_pg, stop_pg, cm_offset; int has_shmem = 0; hw_info_t *local_hw_info; dev_dbg(&link->dev, "pcnet_config\n"); - ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); - if (ret) - goto failed; - - if (!link->irq) - goto failed; - - if (resource_size(link->resource[1]) == 8) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - if ((link->manf_id == MANFID_IBM) && - (link->card_id == PRODID_IBM_HOME_AND_AWAY)) - link->conf.ConfigIndex |= 0x10; - - ret = pcmcia_request_configuration(link, &link->conf); - if (ret) - goto failed; - dev->irq = link->irq; - dev->base_addr = link->resource[0]->start; - if (info->flags & HAS_MISC_REG) { - if ((if_port == 1) || (if_port == 2)) - dev->if_port = if_port; - else - printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n"); - } else { - dev->if_port = 0; - } - - if ((link->conf.ConfigBase == 0x03c0) && - (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { - printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); - printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); - goto failed; - } - - local_hw_info = get_hwinfo(link); - if (local_hw_info == NULL) - local_hw_info = get_prom(link); - if (local_hw_info == NULL) - local_hw_info = get_dl10019(link); - if (local_hw_info == NULL) - local_hw_info = get_ax88190(link); - if (local_hw_info == NULL) - local_hw_info = get_hwired(link); - - if (local_hw_info == NULL) { - printk(KERN_NOTICE "pcnet_cs: unable to read hardware net" - " address for io base %#3lx\n", dev->base_addr); - goto failed; + local_hw_info = pcnet_try_config(link, &has_shmem, 0); + if (!local_hw_info) { + /* check whether forcing io_lines to 16 helps... */ + pcmcia_disable_device(link); + local_hw_info = pcnet_try_config(link, &has_shmem, 1); + if (local_hw_info == NULL) { + dev_notice(&link->dev, "unable to read hardware net" + " address for io base %#3lx\n", dev->base_addr); + goto failed; + } } info->flags = local_hw_info->flags; @@ -1637,6 +1664,7 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), + PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616), PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 6a6b8199a0d6..6c58da2b882c 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -308,7 +308,7 @@ static int mdio_bus_suspend(struct device *dev) * may call phy routines that try to grab the same lock, and that may * lead to a deadlock. */ - if (phydev->attached_dev) + if (phydev->attached_dev && phydev->adjust_link) phy_stop_machine(phydev); if (!mdio_bus_phy_may_suspend(phydev)) @@ -331,7 +331,7 @@ static int mdio_bus_resume(struct device *dev) return ret; no_resume: - if (phydev->attached_dev) + if (phydev->attached_dev && phydev->adjust_link) phy_start_machine(phydev, NULL); return 0; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index c0761197c07e..16ddc77313cb 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -466,6 +466,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, phydev->interface = interface; + phydev->state = PHY_READY; + /* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface) */ diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6695a51e09e9..736b91703b3e 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -1314,8 +1314,13 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; i = 0; list_for_each_entry(pch, &ppp->channels, clist) { - navail += pch->avail = (pch->chan != NULL); - pch->speed = pch->chan->speed; + if (pch->chan) { + pch->avail = 1; + navail++; + pch->speed = pch->chan->speed; + } else { + pch->avail = 0; + } if (pch->avail) { if (skb_queue_empty(&pch->file.xq) || !pch->had_frag) { diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c new file mode 100644 index 000000000000..85eddda276bd --- /dev/null +++ b/drivers/net/pxa168_eth.c @@ -0,0 +1,1666 @@ +/* + * PXA168 ethernet driver. + * Most of the code is derived from mv643xx ethernet driver. + * + * Copyright (C) 2010 Marvell International Ltd. + * Sachin Sanap <ssanap@marvell.com> + * Philip Rakity <prakity@marvell.com> + * Mark Brown <markb@marvell.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. + * + * 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. + */ + +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/tcp.h> +#include <linux/udp.h> +#include <linux/etherdevice.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/workqueue.h> +#include <linux/clk.h> +#include <linux/phy.h> +#include <linux/io.h> +#include <linux/types.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <asm/cacheflush.h> +#include <linux/pxa168_eth.h> + +#define DRIVER_NAME "pxa168-eth" +#define DRIVER_VERSION "0.3" + +/* + * Registers + */ + +#define PHY_ADDRESS 0x0000 +#define SMI 0x0010 +#define PORT_CONFIG 0x0400 +#define PORT_CONFIG_EXT 0x0408 +#define PORT_COMMAND 0x0410 +#define PORT_STATUS 0x0418 +#define HTPR 0x0428 +#define SDMA_CONFIG 0x0440 +#define SDMA_CMD 0x0448 +#define INT_CAUSE 0x0450 +#define INT_W_CLEAR 0x0454 +#define INT_MASK 0x0458 +#define ETH_F_RX_DESC_0 0x0480 +#define ETH_C_RX_DESC_0 0x04A0 +#define ETH_C_TX_DESC_1 0x04E4 + +/* smi register */ +#define SMI_BUSY (1 << 28) /* 0 - Write, 1 - Read */ +#define SMI_R_VALID (1 << 27) /* 0 - Write, 1 - Read */ +#define SMI_OP_W (0 << 26) /* Write operation */ +#define SMI_OP_R (1 << 26) /* Read operation */ + +#define PHY_WAIT_ITERATIONS 10 + +#define PXA168_ETH_PHY_ADDR_DEFAULT 0 +/* RX & TX descriptor command */ +#define BUF_OWNED_BY_DMA (1 << 31) + +/* RX descriptor status */ +#define RX_EN_INT (1 << 23) +#define RX_FIRST_DESC (1 << 17) +#define RX_LAST_DESC (1 << 16) +#define RX_ERROR (1 << 15) + +/* TX descriptor command */ +#define TX_EN_INT (1 << 23) +#define TX_GEN_CRC (1 << 22) +#define TX_ZERO_PADDING (1 << 18) +#define TX_FIRST_DESC (1 << 17) +#define TX_LAST_DESC (1 << 16) +#define TX_ERROR (1 << 15) + +/* SDMA_CMD */ +#define SDMA_CMD_AT (1 << 31) +#define SDMA_CMD_TXDL (1 << 24) +#define SDMA_CMD_TXDH (1 << 23) +#define SDMA_CMD_AR (1 << 15) +#define SDMA_CMD_ERD (1 << 7) + +/* Bit definitions of the Port Config Reg */ +#define PCR_HS (1 << 12) +#define PCR_EN (1 << 7) +#define PCR_PM (1 << 0) + +/* Bit definitions of the Port Config Extend Reg */ +#define PCXR_2BSM (1 << 28) +#define PCXR_DSCP_EN (1 << 21) +#define PCXR_MFL_1518 (0 << 14) +#define PCXR_MFL_1536 (1 << 14) +#define PCXR_MFL_2048 (2 << 14) +#define PCXR_MFL_64K (3 << 14) +#define PCXR_FLP (1 << 11) +#define PCXR_PRIO_TX_OFF 3 +#define PCXR_TX_HIGH_PRI (7 << PCXR_PRIO_TX_OFF) + +/* Bit definitions of the SDMA Config Reg */ +#define SDCR_BSZ_OFF 12 +#define SDCR_BSZ8 (3 << SDCR_BSZ_OFF) +#define SDCR_BSZ4 (2 << SDCR_BSZ_OFF) +#define SDCR_BSZ2 (1 << SDCR_BSZ_OFF) +#define SDCR_BSZ1 (0 << SDCR_BSZ_OFF) +#define SDCR_BLMR (1 << 6) +#define SDCR_BLMT (1 << 7) +#define SDCR_RIFB (1 << 9) +#define SDCR_RC_OFF 2 +#define SDCR_RC_MAX_RETRANS (0xf << SDCR_RC_OFF) + +/* + * Bit definitions of the Interrupt Cause Reg + * and Interrupt MASK Reg is the same + */ +#define ICR_RXBUF (1 << 0) +#define ICR_TXBUF_H (1 << 2) +#define ICR_TXBUF_L (1 << 3) +#define ICR_TXEND_H (1 << 6) +#define ICR_TXEND_L (1 << 7) +#define ICR_RXERR (1 << 8) +#define ICR_TXERR_H (1 << 10) +#define ICR_TXERR_L (1 << 11) +#define ICR_TX_UDR (1 << 13) +#define ICR_MII_CH (1 << 28) + +#define ALL_INTS (ICR_TXBUF_H | ICR_TXBUF_L | ICR_TX_UDR |\ + ICR_TXERR_H | ICR_TXERR_L |\ + ICR_TXEND_H | ICR_TXEND_L |\ + ICR_RXBUF | ICR_RXERR | ICR_MII_CH) + +#define ETH_HW_IP_ALIGN 2 /* hw aligns IP header */ + +#define NUM_RX_DESCS 64 +#define NUM_TX_DESCS 64 + +#define HASH_ADD 0 +#define HASH_DELETE 1 +#define HASH_ADDR_TABLE_SIZE 0x4000 /* 16K (1/2K address - PCR_HS == 1) */ +#define HOP_NUMBER 12 + +/* Bit definitions for Port status */ +#define PORT_SPEED_100 (1 << 0) +#define FULL_DUPLEX (1 << 1) +#define FLOW_CONTROL_ENABLED (1 << 2) +#define LINK_UP (1 << 3) + +/* Bit definitions for work to be done */ +#define WORK_LINK (1 << 0) +#define WORK_TX_DONE (1 << 1) + +/* + * Misc definitions. + */ +#define SKB_DMA_REALIGN ((PAGE_SIZE - NET_SKB_PAD) % SMP_CACHE_BYTES) + +struct rx_desc { + u32 cmd_sts; /* Descriptor command status */ + u16 byte_cnt; /* Descriptor buffer byte count */ + u16 buf_size; /* Buffer size */ + u32 buf_ptr; /* Descriptor buffer pointer */ + u32 next_desc_ptr; /* Next descriptor pointer */ +}; + +struct tx_desc { + u32 cmd_sts; /* Command/status field */ + u16 reserved; + u16 byte_cnt; /* buffer byte count */ + u32 buf_ptr; /* pointer to buffer for this descriptor */ + u32 next_desc_ptr; /* Pointer to next descriptor */ +}; + +struct pxa168_eth_private { + int port_num; /* User Ethernet port number */ + + int rx_resource_err; /* Rx ring resource error flag */ + + /* Next available and first returning Rx resource */ + int rx_curr_desc_q, rx_used_desc_q; + + /* Next available and first returning Tx resource */ + int tx_curr_desc_q, tx_used_desc_q; + + struct rx_desc *p_rx_desc_area; + dma_addr_t rx_desc_dma; + int rx_desc_area_size; + struct sk_buff **rx_skb; + + struct tx_desc *p_tx_desc_area; + dma_addr_t tx_desc_dma; + int tx_desc_area_size; + struct sk_buff **tx_skb; + + struct work_struct tx_timeout_task; + + struct net_device *dev; + struct napi_struct napi; + u8 work_todo; + int skb_size; + + struct net_device_stats stats; + /* Size of Tx Ring per queue */ + int tx_ring_size; + /* Number of tx descriptors in use */ + int tx_desc_count; + /* Size of Rx Ring per queue */ + int rx_ring_size; + /* Number of rx descriptors in use */ + int rx_desc_count; + + /* + * Used in case RX Ring is empty, which can occur when + * system does not have resources (skb's) + */ + struct timer_list timeout; + struct mii_bus *smi_bus; + struct phy_device *phy; + + /* clock */ + struct clk *clk; + struct pxa168_eth_platform_data *pd; + /* + * Ethernet controller base address. + */ + void __iomem *base; + + /* Pointer to the hardware address filter table */ + void *htpr; + dma_addr_t htpr_dma; +}; + +struct addr_table_entry { + __le32 lo; + __le32 hi; +}; + +/* Bit fields of a Hash Table Entry */ +enum hash_table_entry { + HASH_ENTRY_VALID = 1, + SKIP = 2, + HASH_ENTRY_RECEIVE_DISCARD = 4, + HASH_ENTRY_RECEIVE_DISCARD_BIT = 2 +}; + +static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); +static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd); +static int pxa168_init_hw(struct pxa168_eth_private *pep); +static void eth_port_reset(struct net_device *dev); +static void eth_port_start(struct net_device *dev); +static int pxa168_eth_open(struct net_device *dev); +static int pxa168_eth_stop(struct net_device *dev); +static int ethernet_phy_setup(struct net_device *dev); + +static inline u32 rdl(struct pxa168_eth_private *pep, int offset) +{ + return readl(pep->base + offset); +} + +static inline void wrl(struct pxa168_eth_private *pep, int offset, u32 data) +{ + writel(data, pep->base + offset); +} + +static void abort_dma(struct pxa168_eth_private *pep) +{ + int delay; + int max_retries = 40; + + do { + wrl(pep, SDMA_CMD, SDMA_CMD_AR | SDMA_CMD_AT); + udelay(100); + + delay = 10; + while ((rdl(pep, SDMA_CMD) & (SDMA_CMD_AR | SDMA_CMD_AT)) + && delay-- > 0) { + udelay(10); + } + } while (max_retries-- > 0 && delay <= 0); + + if (max_retries <= 0) + printk(KERN_ERR "%s : DMA Stuck\n", __func__); +} + +static int ethernet_phy_get(struct pxa168_eth_private *pep) +{ + unsigned int reg_data; + + reg_data = rdl(pep, PHY_ADDRESS); + + return (reg_data >> (5 * pep->port_num)) & 0x1f; +} + +static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr) +{ + u32 reg_data; + int addr_shift = 5 * pep->port_num; + + reg_data = rdl(pep, PHY_ADDRESS); + reg_data &= ~(0x1f << addr_shift); + reg_data |= (phy_addr & 0x1f) << addr_shift; + wrl(pep, PHY_ADDRESS, reg_data); +} + +static void ethernet_phy_reset(struct pxa168_eth_private *pep) +{ + int data; + + data = phy_read(pep->phy, MII_BMCR); + if (data < 0) + return; + + data |= BMCR_RESET; + if (phy_write(pep->phy, MII_BMCR, data) < 0) + return; + + do { + data = phy_read(pep->phy, MII_BMCR); + } while (data >= 0 && data & BMCR_RESET); +} + +static void rxq_refill(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct sk_buff *skb; + struct rx_desc *p_used_rx_desc; + int used_rx_desc; + + while (pep->rx_desc_count < pep->rx_ring_size) { + int size; + + skb = dev_alloc_skb(pep->skb_size); + if (!skb) + break; + if (SKB_DMA_REALIGN) + skb_reserve(skb, SKB_DMA_REALIGN); + pep->rx_desc_count++; + /* Get 'used' Rx descriptor */ + used_rx_desc = pep->rx_used_desc_q; + p_used_rx_desc = &pep->p_rx_desc_area[used_rx_desc]; + size = skb->end - skb->data; + p_used_rx_desc->buf_ptr = dma_map_single(NULL, + skb->data, + size, + DMA_FROM_DEVICE); + p_used_rx_desc->buf_size = size; + pep->rx_skb[used_rx_desc] = skb; + + /* Return the descriptor to DMA ownership */ + wmb(); + p_used_rx_desc->cmd_sts = BUF_OWNED_BY_DMA | RX_EN_INT; + wmb(); + + /* Move the used descriptor pointer to the next descriptor */ + pep->rx_used_desc_q = (used_rx_desc + 1) % pep->rx_ring_size; + + /* Any Rx return cancels the Rx resource error status */ + pep->rx_resource_err = 0; + + skb_reserve(skb, ETH_HW_IP_ALIGN); + } + + /* + * If RX ring is empty of SKB, set a timer to try allocating + * again at a later time. + */ + if (pep->rx_desc_count == 0) { + pep->timeout.expires = jiffies + (HZ / 10); + add_timer(&pep->timeout); + } +} + +static inline void rxq_refill_timer_wrapper(unsigned long data) +{ + struct pxa168_eth_private *pep = (void *)data; + napi_schedule(&pep->napi); +} + +static inline u8 flip_8_bits(u8 x) +{ + return (((x) & 0x01) << 3) | (((x) & 0x02) << 1) + | (((x) & 0x04) >> 1) | (((x) & 0x08) >> 3) + | (((x) & 0x10) << 3) | (((x) & 0x20) << 1) + | (((x) & 0x40) >> 1) | (((x) & 0x80) >> 3); +} + +static void nibble_swap_every_byte(unsigned char *mac_addr) +{ + int i; + for (i = 0; i < ETH_ALEN; i++) { + mac_addr[i] = ((mac_addr[i] & 0x0f) << 4) | + ((mac_addr[i] & 0xf0) >> 4); + } +} + +static void inverse_every_nibble(unsigned char *mac_addr) +{ + int i; + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = flip_8_bits(mac_addr[i]); +} + +/* + * ---------------------------------------------------------------------------- + * This function will calculate the hash function of the address. + * Inputs + * mac_addr_orig - MAC address. + * Outputs + * return the calculated entry. + */ +static u32 hash_function(unsigned char *mac_addr_orig) +{ + u32 hash_result; + u32 addr0; + u32 addr1; + u32 addr2; + u32 addr3; + unsigned char mac_addr[ETH_ALEN]; + + /* Make a copy of MAC address since we are going to performe bit + * operations on it + */ + memcpy(mac_addr, mac_addr_orig, ETH_ALEN); + + nibble_swap_every_byte(mac_addr); + inverse_every_nibble(mac_addr); + + addr0 = (mac_addr[5] >> 2) & 0x3f; + addr1 = (mac_addr[5] & 0x03) | (((mac_addr[4] & 0x7f)) << 2); + addr2 = ((mac_addr[4] & 0x80) >> 7) | mac_addr[3] << 1; + addr3 = (mac_addr[2] & 0xff) | ((mac_addr[1] & 1) << 8); + + hash_result = (addr0 << 9) | (addr1 ^ addr2 ^ addr3); + hash_result = hash_result & 0x07ff; + return hash_result; +} + +/* + * ---------------------------------------------------------------------------- + * This function will add/del an entry to the address table. + * Inputs + * pep - ETHERNET . + * mac_addr - MAC address. + * skip - if 1, skip this address.Used in case of deleting an entry which is a + * part of chain in the hash table.We cant just delete the entry since + * that will break the chain.We need to defragment the tables time to + * time. + * rd - 0 Discard packet upon match. + * - 1 Receive packet upon match. + * Outputs + * address table entry is added/deleted. + * 0 if success. + * -ENOSPC if table full + */ +static int add_del_hash_entry(struct pxa168_eth_private *pep, + unsigned char *mac_addr, + u32 rd, u32 skip, int del) +{ + struct addr_table_entry *entry, *start; + u32 new_high; + u32 new_low; + u32 i; + + new_low = (((mac_addr[1] >> 4) & 0xf) << 15) + | (((mac_addr[1] >> 0) & 0xf) << 11) + | (((mac_addr[0] >> 4) & 0xf) << 7) + | (((mac_addr[0] >> 0) & 0xf) << 3) + | (((mac_addr[3] >> 4) & 0x1) << 31) + | (((mac_addr[3] >> 0) & 0xf) << 27) + | (((mac_addr[2] >> 4) & 0xf) << 23) + | (((mac_addr[2] >> 0) & 0xf) << 19) + | (skip << SKIP) | (rd << HASH_ENTRY_RECEIVE_DISCARD_BIT) + | HASH_ENTRY_VALID; + + new_high = (((mac_addr[5] >> 4) & 0xf) << 15) + | (((mac_addr[5] >> 0) & 0xf) << 11) + | (((mac_addr[4] >> 4) & 0xf) << 7) + | (((mac_addr[4] >> 0) & 0xf) << 3) + | (((mac_addr[3] >> 5) & 0x7) << 0); + + /* + * Pick the appropriate table, start scanning for free/reusable + * entries at the index obtained by hashing the specified MAC address + */ + start = (struct addr_table_entry *)(pep->htpr); + entry = start + hash_function(mac_addr); + for (i = 0; i < HOP_NUMBER; i++) { + if (!(le32_to_cpu(entry->lo) & HASH_ENTRY_VALID)) { + break; + } else { + /* if same address put in same position */ + if (((le32_to_cpu(entry->lo) & 0xfffffff8) == + (new_low & 0xfffffff8)) && + (le32_to_cpu(entry->hi) == new_high)) { + break; + } + } + if (entry == start + 0x7ff) + entry = start; + else + entry++; + } + + if (((le32_to_cpu(entry->lo) & 0xfffffff8) != (new_low & 0xfffffff8)) && + (le32_to_cpu(entry->hi) != new_high) && del) + return 0; + + if (i == HOP_NUMBER) { + if (!del) { + printk(KERN_INFO "%s: table section is full, need to " + "move to 16kB implementation?\n", + __FILE__); + return -ENOSPC; + } else + return 0; + } + + /* + * Update the selected entry + */ + if (del) { + entry->hi = 0; + entry->lo = 0; + } else { + entry->hi = cpu_to_le32(new_high); + entry->lo = cpu_to_le32(new_low); + } + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * Create an addressTable entry from MAC address info + * found in the specifed net_device struct + * + * Input : pointer to ethernet interface network device structure + * Output : N/A + */ +static void update_hash_table_mac_address(struct pxa168_eth_private *pep, + unsigned char *oaddr, + unsigned char *addr) +{ + /* Delete old entry */ + if (oaddr) + add_del_hash_entry(pep, oaddr, 1, 0, HASH_DELETE); + /* Add new entry */ + add_del_hash_entry(pep, addr, 1, 0, HASH_ADD); +} + +static int init_hash_table(struct pxa168_eth_private *pep) +{ + /* + * Hardware expects CPU to build a hash table based on a predefined + * hash function and populate it based on hardware address. The + * location of the hash table is identified by 32-bit pointer stored + * in HTPR internal register. Two possible sizes exists for the hash + * table 8kB (256kB of DRAM required (4 x 64 kB banks)) and 1/2kB + * (16kB of DRAM required (4 x 4 kB banks)).We currently only support + * 1/2kB. + */ + /* TODO: Add support for 8kB hash table and alternative hash + * function.Driver can dynamically switch to them if the 1/2kB hash + * table is full. + */ + if (pep->htpr == NULL) { + pep->htpr = dma_alloc_coherent(pep->dev->dev.parent, + HASH_ADDR_TABLE_SIZE, + &pep->htpr_dma, GFP_KERNEL); + if (pep->htpr == NULL) + return -ENOMEM; + } + memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE); + wrl(pep, HTPR, pep->htpr_dma); + return 0; +} + +static void pxa168_eth_set_rx_mode(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct netdev_hw_addr *ha; + u32 val; + + val = rdl(pep, PORT_CONFIG); + if (dev->flags & IFF_PROMISC) + val |= PCR_PM; + else + val &= ~PCR_PM; + wrl(pep, PORT_CONFIG, val); + + /* + * Remove the old list of MAC address and add dev->addr + * and multicast address. + */ + memset(pep->htpr, 0, HASH_ADDR_TABLE_SIZE); + update_hash_table_mac_address(pep, NULL, dev->dev_addr); + + netdev_for_each_mc_addr(ha, dev) + update_hash_table_mac_address(pep, NULL, ha->addr); +} + +static int pxa168_eth_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *sa = addr; + struct pxa168_eth_private *pep = netdev_priv(dev); + unsigned char oldMac[ETH_ALEN]; + + if (!is_valid_ether_addr(sa->sa_data)) + return -EINVAL; + memcpy(oldMac, dev->dev_addr, ETH_ALEN); + memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); + netif_addr_lock_bh(dev); + update_hash_table_mac_address(pep, oldMac, dev->dev_addr); + netif_addr_unlock_bh(dev); + return 0; +} + +static void eth_port_start(struct net_device *dev) +{ + unsigned int val = 0; + struct pxa168_eth_private *pep = netdev_priv(dev); + int tx_curr_desc, rx_curr_desc; + + /* Perform PHY reset, if there is a PHY. */ + if (pep->phy != NULL) { + struct ethtool_cmd cmd; + + pxa168_get_settings(pep->dev, &cmd); + ethernet_phy_reset(pep); + pxa168_set_settings(pep->dev, &cmd); + } + + /* Assignment of Tx CTRP of given queue */ + tx_curr_desc = pep->tx_curr_desc_q; + wrl(pep, ETH_C_TX_DESC_1, + (u32) (pep->tx_desc_dma + tx_curr_desc * sizeof(struct tx_desc))); + + /* Assignment of Rx CRDP of given queue */ + rx_curr_desc = pep->rx_curr_desc_q; + wrl(pep, ETH_C_RX_DESC_0, + (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc))); + + wrl(pep, ETH_F_RX_DESC_0, + (u32) (pep->rx_desc_dma + rx_curr_desc * sizeof(struct rx_desc))); + + /* Clear all interrupts */ + wrl(pep, INT_CAUSE, 0); + + /* Enable all interrupts for receive, transmit and error. */ + wrl(pep, INT_MASK, ALL_INTS); + + val = rdl(pep, PORT_CONFIG); + val |= PCR_EN; + wrl(pep, PORT_CONFIG, val); + + /* Start RX DMA engine */ + val = rdl(pep, SDMA_CMD); + val |= SDMA_CMD_ERD; + wrl(pep, SDMA_CMD, val); +} + +static void eth_port_reset(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + unsigned int val = 0; + + /* Stop all interrupts for receive, transmit and error. */ + wrl(pep, INT_MASK, 0); + + /* Clear all interrupts */ + wrl(pep, INT_CAUSE, 0); + + /* Stop RX DMA */ + val = rdl(pep, SDMA_CMD); + val &= ~SDMA_CMD_ERD; /* abort dma command */ + + /* Abort any transmit and receive operations and put DMA + * in idle state. + */ + abort_dma(pep); + + /* Disable port */ + val = rdl(pep, PORT_CONFIG); + val &= ~PCR_EN; + wrl(pep, PORT_CONFIG, val); +} + +/* + * txq_reclaim - Free the tx desc data for completed descriptors + * If force is non-zero, frees uncompleted descriptors as well + */ +static int txq_reclaim(struct net_device *dev, int force) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct tx_desc *desc; + u32 cmd_sts; + struct sk_buff *skb; + int tx_index; + dma_addr_t addr; + int count; + int released = 0; + + netif_tx_lock(dev); + + pep->work_todo &= ~WORK_TX_DONE; + while (pep->tx_desc_count > 0) { + tx_index = pep->tx_used_desc_q; + desc = &pep->p_tx_desc_area[tx_index]; + cmd_sts = desc->cmd_sts; + if (!force && (cmd_sts & BUF_OWNED_BY_DMA)) { + if (released > 0) { + goto txq_reclaim_end; + } else { + released = -1; + goto txq_reclaim_end; + } + } + pep->tx_used_desc_q = (tx_index + 1) % pep->tx_ring_size; + pep->tx_desc_count--; + addr = desc->buf_ptr; + count = desc->byte_cnt; + skb = pep->tx_skb[tx_index]; + if (skb) + pep->tx_skb[tx_index] = NULL; + + if (cmd_sts & TX_ERROR) { + if (net_ratelimit()) + printk(KERN_ERR "%s: Error in TX\n", dev->name); + dev->stats.tx_errors++; + } + dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); + if (skb) + dev_kfree_skb_irq(skb); + released++; + } +txq_reclaim_end: + netif_tx_unlock(dev); + return released; +} + +static void pxa168_eth_tx_timeout(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + printk(KERN_INFO "%s: TX timeout desc_count %d\n", + dev->name, pep->tx_desc_count); + + schedule_work(&pep->tx_timeout_task); +} + +static void pxa168_eth_tx_timeout_task(struct work_struct *work) +{ + struct pxa168_eth_private *pep = container_of(work, + struct pxa168_eth_private, + tx_timeout_task); + struct net_device *dev = pep->dev; + pxa168_eth_stop(dev); + pxa168_eth_open(dev); +} + +static int rxq_process(struct net_device *dev, int budget) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + unsigned int received_packets = 0; + struct sk_buff *skb; + + while (budget-- > 0) { + int rx_next_curr_desc, rx_curr_desc, rx_used_desc; + struct rx_desc *rx_desc; + unsigned int cmd_sts; + + /* Do not process Rx ring in case of Rx ring resource error */ + if (pep->rx_resource_err) + break; + rx_curr_desc = pep->rx_curr_desc_q; + rx_used_desc = pep->rx_used_desc_q; + rx_desc = &pep->p_rx_desc_area[rx_curr_desc]; + cmd_sts = rx_desc->cmd_sts; + rmb(); + if (cmd_sts & (BUF_OWNED_BY_DMA)) + break; + skb = pep->rx_skb[rx_curr_desc]; + pep->rx_skb[rx_curr_desc] = NULL; + + rx_next_curr_desc = (rx_curr_desc + 1) % pep->rx_ring_size; + pep->rx_curr_desc_q = rx_next_curr_desc; + + /* Rx descriptors exhausted. */ + /* Set the Rx ring resource error flag */ + if (rx_next_curr_desc == rx_used_desc) + pep->rx_resource_err = 1; + pep->rx_desc_count--; + dma_unmap_single(NULL, rx_desc->buf_ptr, + rx_desc->buf_size, + DMA_FROM_DEVICE); + received_packets++; + /* + * Update statistics. + * Note byte count includes 4 byte CRC count + */ + stats->rx_packets++; + stats->rx_bytes += rx_desc->byte_cnt; + /* + * In case received a packet without first / last bits on OR + * the error summary bit is on, the packets needs to be droped. + */ + if (((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) != + (RX_FIRST_DESC | RX_LAST_DESC)) + || (cmd_sts & RX_ERROR)) { + + stats->rx_dropped++; + if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) != + (RX_FIRST_DESC | RX_LAST_DESC)) { + if (net_ratelimit()) + printk(KERN_ERR + "%s: Rx pkt on multiple desc\n", + dev->name); + } + if (cmd_sts & RX_ERROR) + stats->rx_errors++; + dev_kfree_skb_irq(skb); + } else { + /* + * The -4 is for the CRC in the trailer of the + * received packet + */ + skb_put(skb, rx_desc->byte_cnt - 4); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + } + dev->last_rx = jiffies; + } + /* Fill RX ring with skb's */ + rxq_refill(dev); + return received_packets; +} + +static int pxa168_eth_collect_events(struct pxa168_eth_private *pep, + struct net_device *dev) +{ + u32 icr; + int ret = 0; + + icr = rdl(pep, INT_CAUSE); + if (icr == 0) + return IRQ_NONE; + + wrl(pep, INT_CAUSE, ~icr); + if (icr & (ICR_TXBUF_H | ICR_TXBUF_L)) { + pep->work_todo |= WORK_TX_DONE; + ret = 1; + } + if (icr & ICR_RXBUF) + ret = 1; + if (icr & ICR_MII_CH) { + pep->work_todo |= WORK_LINK; + ret = 1; + } + return ret; +} + +static void handle_link_event(struct pxa168_eth_private *pep) +{ + struct net_device *dev = pep->dev; + u32 port_status; + int speed; + int duplex; + int fc; + + port_status = rdl(pep, PORT_STATUS); + if (!(port_status & LINK_UP)) { + if (netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link down\n", dev->name); + netif_carrier_off(dev); + txq_reclaim(dev, 1); + } + return; + } + if (port_status & PORT_SPEED_100) + speed = 100; + else + speed = 10; + + duplex = (port_status & FULL_DUPLEX) ? 1 : 0; + fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0; + printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " + "flow control %sabled\n", dev->name, + speed, duplex ? "full" : "half", fc ? "en" : "dis"); + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); +} + +static irqreturn_t pxa168_eth_int_handler(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + struct pxa168_eth_private *pep = netdev_priv(dev); + + if (unlikely(!pxa168_eth_collect_events(pep, dev))) + return IRQ_NONE; + /* Disable interrupts */ + wrl(pep, INT_MASK, 0); + napi_schedule(&pep->napi); + return IRQ_HANDLED; +} + +static void pxa168_eth_recalc_skb_size(struct pxa168_eth_private *pep) +{ + int skb_size; + + /* + * Reserve 2+14 bytes for an ethernet header (the hardware + * automatically prepends 2 bytes of dummy data to each + * received packet), 16 bytes for up to four VLAN tags, and + * 4 bytes for the trailing FCS -- 36 bytes total. + */ + skb_size = pep->dev->mtu + 36; + + /* + * Make sure that the skb size is a multiple of 8 bytes, as + * the lower three bits of the receive descriptor's buffer + * size field are ignored by the hardware. + */ + pep->skb_size = (skb_size + 7) & ~7; + + /* + * If NET_SKB_PAD is smaller than a cache line, + * netdev_alloc_skb() will cause skb->data to be misaligned + * to a cache line boundary. If this is the case, include + * some extra space to allow re-aligning the data area. + */ + pep->skb_size += SKB_DMA_REALIGN; + +} + +static int set_port_config_ext(struct pxa168_eth_private *pep) +{ + int skb_size; + + pxa168_eth_recalc_skb_size(pep); + if (pep->skb_size <= 1518) + skb_size = PCXR_MFL_1518; + else if (pep->skb_size <= 1536) + skb_size = PCXR_MFL_1536; + else if (pep->skb_size <= 2048) + skb_size = PCXR_MFL_2048; + else + skb_size = PCXR_MFL_64K; + + /* Extended Port Configuration */ + wrl(pep, + PORT_CONFIG_EXT, PCXR_2BSM | /* Two byte prefix aligns IP hdr */ + PCXR_DSCP_EN | /* Enable DSCP in IP */ + skb_size | PCXR_FLP | /* do not force link pass */ + PCXR_TX_HIGH_PRI); /* Transmit - high priority queue */ + + return 0; +} + +static int pxa168_init_hw(struct pxa168_eth_private *pep) +{ + int err = 0; + + /* Disable interrupts */ + wrl(pep, INT_MASK, 0); + wrl(pep, INT_CAUSE, 0); + /* Write to ICR to clear interrupts. */ + wrl(pep, INT_W_CLEAR, 0); + /* Abort any transmit and receive operations and put DMA + * in idle state. + */ + abort_dma(pep); + /* Initialize address hash table */ + err = init_hash_table(pep); + if (err) + return err; + /* SDMA configuration */ + wrl(pep, SDMA_CONFIG, SDCR_BSZ8 | /* Burst size = 32 bytes */ + SDCR_RIFB | /* Rx interrupt on frame */ + SDCR_BLMT | /* Little endian transmit */ + SDCR_BLMR | /* Little endian receive */ + SDCR_RC_MAX_RETRANS); /* Max retransmit count */ + /* Port Configuration */ + wrl(pep, PORT_CONFIG, PCR_HS); /* Hash size is 1/2kb */ + set_port_config_ext(pep); + + return err; +} + +static int rxq_init(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct rx_desc *p_rx_desc; + int size = 0, i = 0; + int rx_desc_num = pep->rx_ring_size; + + /* Allocate RX skb rings */ + pep->rx_skb = kmalloc(sizeof(*pep->rx_skb) * pep->rx_ring_size, + GFP_KERNEL); + if (!pep->rx_skb) { + printk(KERN_ERR "%s: Cannot alloc RX skb ring\n", dev->name); + return -ENOMEM; + } + /* Allocate RX ring */ + pep->rx_desc_count = 0; + size = pep->rx_ring_size * sizeof(struct rx_desc); + pep->rx_desc_area_size = size; + pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size, + &pep->rx_desc_dma, GFP_KERNEL); + if (!pep->p_rx_desc_area) { + printk(KERN_ERR "%s: Cannot alloc RX ring (size %d bytes)\n", + dev->name, size); + goto out; + } + memset((void *)pep->p_rx_desc_area, 0, size); + /* initialize the next_desc_ptr links in the Rx descriptors ring */ + p_rx_desc = (struct rx_desc *)pep->p_rx_desc_area; + for (i = 0; i < rx_desc_num; i++) { + p_rx_desc[i].next_desc_ptr = pep->rx_desc_dma + + ((i + 1) % rx_desc_num) * sizeof(struct rx_desc); + } + /* Save Rx desc pointer to driver struct. */ + pep->rx_curr_desc_q = 0; + pep->rx_used_desc_q = 0; + pep->rx_desc_area_size = rx_desc_num * sizeof(struct rx_desc); + return 0; +out: + kfree(pep->rx_skb); + return -ENOMEM; +} + +static void rxq_deinit(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + int curr; + + /* Free preallocated skb's on RX rings */ + for (curr = 0; pep->rx_desc_count && curr < pep->rx_ring_size; curr++) { + if (pep->rx_skb[curr]) { + dev_kfree_skb(pep->rx_skb[curr]); + pep->rx_desc_count--; + } + } + if (pep->rx_desc_count) + printk(KERN_ERR + "Error in freeing Rx Ring. %d skb's still\n", + pep->rx_desc_count); + /* Free RX ring */ + if (pep->p_rx_desc_area) + dma_free_coherent(pep->dev->dev.parent, pep->rx_desc_area_size, + pep->p_rx_desc_area, pep->rx_desc_dma); + kfree(pep->rx_skb); +} + +static int txq_init(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct tx_desc *p_tx_desc; + int size = 0, i = 0; + int tx_desc_num = pep->tx_ring_size; + + pep->tx_skb = kmalloc(sizeof(*pep->tx_skb) * pep->tx_ring_size, + GFP_KERNEL); + if (!pep->tx_skb) { + printk(KERN_ERR "%s: Cannot alloc TX skb ring\n", dev->name); + return -ENOMEM; + } + /* Allocate TX ring */ + pep->tx_desc_count = 0; + size = pep->tx_ring_size * sizeof(struct tx_desc); + pep->tx_desc_area_size = size; + pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size, + &pep->tx_desc_dma, GFP_KERNEL); + if (!pep->p_tx_desc_area) { + printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n", + dev->name, size); + goto out; + } + memset((void *)pep->p_tx_desc_area, 0, pep->tx_desc_area_size); + /* Initialize the next_desc_ptr links in the Tx descriptors ring */ + p_tx_desc = (struct tx_desc *)pep->p_tx_desc_area; + for (i = 0; i < tx_desc_num; i++) { + p_tx_desc[i].next_desc_ptr = pep->tx_desc_dma + + ((i + 1) % tx_desc_num) * sizeof(struct tx_desc); + } + pep->tx_curr_desc_q = 0; + pep->tx_used_desc_q = 0; + pep->tx_desc_area_size = tx_desc_num * sizeof(struct tx_desc); + return 0; +out: + kfree(pep->tx_skb); + return -ENOMEM; +} + +static void txq_deinit(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + /* Free outstanding skb's on TX ring */ + txq_reclaim(dev, 1); + BUG_ON(pep->tx_used_desc_q != pep->tx_curr_desc_q); + /* Free TX ring */ + if (pep->p_tx_desc_area) + dma_free_coherent(pep->dev->dev.parent, pep->tx_desc_area_size, + pep->p_tx_desc_area, pep->tx_desc_dma); + kfree(pep->tx_skb); +} + +static int pxa168_eth_open(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + int err; + + err = request_irq(dev->irq, pxa168_eth_int_handler, + IRQF_DISABLED, dev->name, dev); + if (err) { + dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n"); + return -EAGAIN; + } + pep->rx_resource_err = 0; + err = rxq_init(dev); + if (err != 0) + goto out_free_irq; + err = txq_init(dev); + if (err != 0) + goto out_free_rx_skb; + pep->rx_used_desc_q = 0; + pep->rx_curr_desc_q = 0; + + /* Fill RX ring with skb's */ + rxq_refill(dev); + pep->rx_used_desc_q = 0; + pep->rx_curr_desc_q = 0; + netif_carrier_off(dev); + eth_port_start(dev); + napi_enable(&pep->napi); + return 0; +out_free_rx_skb: + rxq_deinit(dev); +out_free_irq: + free_irq(dev->irq, dev); + return err; +} + +static int pxa168_eth_stop(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + eth_port_reset(dev); + + /* Disable interrupts */ + wrl(pep, INT_MASK, 0); + wrl(pep, INT_CAUSE, 0); + /* Write to ICR to clear interrupts. */ + wrl(pep, INT_W_CLEAR, 0); + napi_disable(&pep->napi); + del_timer_sync(&pep->timeout); + netif_carrier_off(dev); + free_irq(dev->irq, dev); + rxq_deinit(dev); + txq_deinit(dev); + + return 0; +} + +static int pxa168_eth_change_mtu(struct net_device *dev, int mtu) +{ + int retval; + struct pxa168_eth_private *pep = netdev_priv(dev); + + if ((mtu > 9500) || (mtu < 68)) + return -EINVAL; + + dev->mtu = mtu; + retval = set_port_config_ext(pep); + + if (!netif_running(dev)) + return 0; + + /* + * Stop and then re-open the interface. This will allocate RX + * skbs of the new MTU. + * There is a possible danger that the open will not succeed, + * due to memory being full. + */ + pxa168_eth_stop(dev); + if (pxa168_eth_open(dev)) { + dev_printk(KERN_ERR, &dev->dev, + "fatal error on re-opening device after " + "MTU change\n"); + } + + return 0; +} + +static int eth_alloc_tx_desc_index(struct pxa168_eth_private *pep) +{ + int tx_desc_curr; + + tx_desc_curr = pep->tx_curr_desc_q; + pep->tx_curr_desc_q = (tx_desc_curr + 1) % pep->tx_ring_size; + BUG_ON(pep->tx_curr_desc_q == pep->tx_used_desc_q); + pep->tx_desc_count++; + + return tx_desc_curr; +} + +static int pxa168_rx_poll(struct napi_struct *napi, int budget) +{ + struct pxa168_eth_private *pep = + container_of(napi, struct pxa168_eth_private, napi); + struct net_device *dev = pep->dev; + int work_done = 0; + + if (unlikely(pep->work_todo & WORK_LINK)) { + pep->work_todo &= ~(WORK_LINK); + handle_link_event(pep); + } + /* + * We call txq_reclaim every time since in NAPI interupts are disabled + * and due to this we miss the TX_DONE interrupt,which is not updated in + * interrupt status register. + */ + txq_reclaim(dev, 0); + if (netif_queue_stopped(dev) + && pep->tx_ring_size - pep->tx_desc_count > 1) { + netif_wake_queue(dev); + } + work_done = rxq_process(dev, budget); + if (work_done < budget) { + napi_complete(napi); + wrl(pep, INT_MASK, ALL_INTS); + } + + return work_done; +} + +static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + struct net_device_stats *stats = &dev->stats; + struct tx_desc *desc; + int tx_index; + int length; + + tx_index = eth_alloc_tx_desc_index(pep); + desc = &pep->p_tx_desc_area[tx_index]; + length = skb->len; + pep->tx_skb[tx_index] = skb; + desc->byte_cnt = length; + desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); + wmb(); + desc->cmd_sts = BUF_OWNED_BY_DMA | TX_GEN_CRC | TX_FIRST_DESC | + TX_ZERO_PADDING | TX_LAST_DESC | TX_EN_INT; + wmb(); + wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD); + + stats->tx_bytes += skb->len; + stats->tx_packets++; + dev->trans_start = jiffies; + if (pep->tx_ring_size - pep->tx_desc_count <= 1) { + /* We handled the current skb, but now we are out of space.*/ + netif_stop_queue(dev); + } + + return NETDEV_TX_OK; +} + +static int smi_wait_ready(struct pxa168_eth_private *pep) +{ + int i = 0; + + /* wait for the SMI register to become available */ + for (i = 0; rdl(pep, SMI) & SMI_BUSY; i++) { + if (i == PHY_WAIT_ITERATIONS) + return -ETIMEDOUT; + msleep(10); + } + + return 0; +} + +static int pxa168_smi_read(struct mii_bus *bus, int phy_addr, int regnum) +{ + struct pxa168_eth_private *pep = bus->priv; + int i = 0; + int val; + + if (smi_wait_ready(pep)) { + printk(KERN_WARNING "pxa168_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } + wrl(pep, SMI, (phy_addr << 16) | (regnum << 21) | SMI_OP_R); + /* now wait for the data to be valid */ + for (i = 0; !((val = rdl(pep, SMI)) & SMI_R_VALID); i++) { + if (i == PHY_WAIT_ITERATIONS) { + printk(KERN_WARNING + "pxa168_eth: SMI bus read not valid\n"); + return -ENODEV; + } + msleep(10); + } + + return val & 0xffff; +} + +static int pxa168_smi_write(struct mii_bus *bus, int phy_addr, int regnum, + u16 value) +{ + struct pxa168_eth_private *pep = bus->priv; + + if (smi_wait_ready(pep)) { + printk(KERN_WARNING "pxa168_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } + + wrl(pep, SMI, (phy_addr << 16) | (regnum << 21) | + SMI_OP_W | (value & 0xffff)); + + if (smi_wait_ready(pep)) { + printk(KERN_ERR "pxa168_eth: SMI bus busy timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int pxa168_eth_do_ioctl(struct net_device *dev, struct ifreq *ifr, + int cmd) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + if (pep->phy != NULL) + return phy_mii_ioctl(pep->phy, ifr, cmd); + + return -EOPNOTSUPP; +} + +static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr) +{ + struct mii_bus *bus = pep->smi_bus; + struct phy_device *phydev; + int start; + int num; + int i; + + if (phy_addr == PXA168_ETH_PHY_ADDR_DEFAULT) { + /* Scan entire range */ + start = ethernet_phy_get(pep); + num = 32; + } else { + /* Use phy addr specific to platform */ + start = phy_addr & 0x1f; + num = 1; + } + phydev = NULL; + for (i = 0; i < num; i++) { + int addr = (start + i) & 0x1f; + if (bus->phy_map[addr] == NULL) + mdiobus_scan(bus, addr); + + if (phydev == NULL) { + phydev = bus->phy_map[addr]; + if (phydev != NULL) + ethernet_phy_set_addr(pep, addr); + } + } + + return phydev; +} + +static void phy_init(struct pxa168_eth_private *pep, int speed, int duplex) +{ + struct phy_device *phy = pep->phy; + ethernet_phy_reset(pep); + + phy_attach(pep->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_MII); + + if (speed == 0) { + phy->autoneg = AUTONEG_ENABLE; + phy->speed = 0; + phy->duplex = 0; + phy->supported &= PHY_BASIC_FEATURES; + phy->advertising = phy->supported | ADVERTISED_Autoneg; + } else { + phy->autoneg = AUTONEG_DISABLE; + phy->advertising = 0; + phy->speed = speed; + phy->duplex = duplex; + } + phy_start_aneg(phy); +} + +static int ethernet_phy_setup(struct net_device *dev) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + if (pep->pd->init) + pep->pd->init(); + pep->phy = phy_scan(pep, pep->pd->phy_addr & 0x1f); + if (pep->phy != NULL) + phy_init(pep, pep->pd->speed, pep->pd->duplex); + update_hash_table_mac_address(pep, NULL, dev->dev_addr); + + return 0; +} + +static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + int err; + + err = phy_read_status(pep->phy); + if (err == 0) + err = phy_ethtool_gset(pep->phy, cmd); + + return err; +} + +static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pxa168_eth_private *pep = netdev_priv(dev); + + return phy_ethtool_sset(pep->phy, cmd); +} + +static void pxa168_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strncpy(info->driver, DRIVER_NAME, 32); + strncpy(info->version, DRIVER_VERSION, 32); + strncpy(info->fw_version, "N/A", 32); + strncpy(info->bus_info, "N/A", 32); +} + +static u32 pxa168_get_link(struct net_device *dev) +{ + return !!netif_carrier_ok(dev); +} + +static const struct ethtool_ops pxa168_ethtool_ops = { + .get_settings = pxa168_get_settings, + .set_settings = pxa168_set_settings, + .get_drvinfo = pxa168_get_drvinfo, + .get_link = pxa168_get_link, +}; + +static const struct net_device_ops pxa168_eth_netdev_ops = { + .ndo_open = pxa168_eth_open, + .ndo_stop = pxa168_eth_stop, + .ndo_start_xmit = pxa168_eth_start_xmit, + .ndo_set_rx_mode = pxa168_eth_set_rx_mode, + .ndo_set_mac_address = pxa168_eth_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = pxa168_eth_do_ioctl, + .ndo_change_mtu = pxa168_eth_change_mtu, + .ndo_tx_timeout = pxa168_eth_tx_timeout, +}; + +static int pxa168_eth_probe(struct platform_device *pdev) +{ + struct pxa168_eth_private *pep = NULL; + struct net_device *dev = NULL; + struct resource *res; + struct clk *clk; + int err; + + printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n"); + + clk = clk_get(&pdev->dev, "MFUCLK"); + if (IS_ERR(clk)) { + printk(KERN_ERR "%s: Fast Ethernet failed to get clock\n", + DRIVER_NAME); + return -ENODEV; + } + clk_enable(clk); + + dev = alloc_etherdev(sizeof(struct pxa168_eth_private)); + if (!dev) { + err = -ENOMEM; + goto err_clk; + } + + platform_set_drvdata(pdev, dev); + pep = netdev_priv(dev); + pep->dev = dev; + pep->clk = clk; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -ENODEV; + goto err_netdev; + } + pep->base = ioremap(res->start, res->end - res->start + 1); + if (pep->base == NULL) { + err = -ENOMEM; + goto err_netdev; + } + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + BUG_ON(!res); + dev->irq = res->start; + dev->netdev_ops = &pxa168_eth_netdev_ops; + dev->watchdog_timeo = 2 * HZ; + dev->base_addr = 0; + SET_ETHTOOL_OPS(dev, &pxa168_ethtool_ops); + + INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task); + + printk(KERN_INFO "%s:Using random mac address\n", DRIVER_NAME); + random_ether_addr(dev->dev_addr); + + pep->pd = pdev->dev.platform_data; + pep->rx_ring_size = NUM_RX_DESCS; + if (pep->pd->rx_queue_size) + pep->rx_ring_size = pep->pd->rx_queue_size; + + pep->tx_ring_size = NUM_TX_DESCS; + if (pep->pd->tx_queue_size) + pep->tx_ring_size = pep->pd->tx_queue_size; + + pep->port_num = pep->pd->port_number; + /* Hardware supports only 3 ports */ + BUG_ON(pep->port_num > 2); + netif_napi_add(dev, &pep->napi, pxa168_rx_poll, pep->rx_ring_size); + + memset(&pep->timeout, 0, sizeof(struct timer_list)); + init_timer(&pep->timeout); + pep->timeout.function = rxq_refill_timer_wrapper; + pep->timeout.data = (unsigned long)pep; + + pep->smi_bus = mdiobus_alloc(); + if (pep->smi_bus == NULL) { + err = -ENOMEM; + goto err_base; + } + pep->smi_bus->priv = pep; + pep->smi_bus->name = "pxa168_eth smi"; + pep->smi_bus->read = pxa168_smi_read; + pep->smi_bus->write = pxa168_smi_write; + snprintf(pep->smi_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); + pep->smi_bus->parent = &pdev->dev; + pep->smi_bus->phy_mask = 0xffffffff; + err = mdiobus_register(pep->smi_bus); + if (err) + goto err_free_mdio; + + pxa168_init_hw(pep); + err = ethernet_phy_setup(dev); + if (err) + goto err_mdiobus; + SET_NETDEV_DEV(dev, &pdev->dev); + err = register_netdev(dev); + if (err) + goto err_mdiobus; + return 0; + +err_mdiobus: + mdiobus_unregister(pep->smi_bus); +err_free_mdio: + mdiobus_free(pep->smi_bus); +err_base: + iounmap(pep->base); +err_netdev: + free_netdev(dev); +err_clk: + clk_disable(clk); + clk_put(clk); + return err; +} + +static int pxa168_eth_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct pxa168_eth_private *pep = netdev_priv(dev); + + if (pep->htpr) { + dma_free_coherent(pep->dev->dev.parent, HASH_ADDR_TABLE_SIZE, + pep->htpr, pep->htpr_dma); + pep->htpr = NULL; + } + if (pep->clk) { + clk_disable(pep->clk); + clk_put(pep->clk); + pep->clk = NULL; + } + if (pep->phy != NULL) + phy_detach(pep->phy); + + iounmap(pep->base); + pep->base = NULL; + mdiobus_unregister(pep->smi_bus); + mdiobus_free(pep->smi_bus); + unregister_netdev(dev); + flush_scheduled_work(); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + return 0; +} + +static void pxa168_eth_shutdown(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + eth_port_reset(dev); +} + +#ifdef CONFIG_PM +static int pxa168_eth_resume(struct platform_device *pdev) +{ + return -ENOSYS; +} + +static int pxa168_eth_suspend(struct platform_device *pdev, pm_message_t state) +{ + return -ENOSYS; +} + +#else +#define pxa168_eth_resume NULL +#define pxa168_eth_suspend NULL +#endif + +static struct platform_driver pxa168_eth_driver = { + .probe = pxa168_eth_probe, + .remove = pxa168_eth_remove, + .shutdown = pxa168_eth_shutdown, + .resume = pxa168_eth_resume, + .suspend = pxa168_eth_suspend, + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init pxa168_init_module(void) +{ + return platform_driver_register(&pxa168_eth_driver); +} + +static void __exit pxa168_cleanup_module(void) +{ + platform_driver_unregister(&pxa168_eth_driver); +} + +module_init(pxa168_init_module); +module_exit(pxa168_cleanup_module); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Ethernet driver for Marvell PXA168"); +MODULE_ALIAS("platform:pxa168_eth"); diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 75ba744b173c..2c7cf0b64811 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1316,7 +1316,7 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, return -ENOMEM; } - skb_reserve(skb, 2); + skb_reserve(skb, NET_IP_ALIGN); dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, PCI_DMA_FROMDEVICE); @@ -1404,7 +1404,6 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); @@ -1466,8 +1465,6 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, skb_put(skb, lro_length + data_offset); - skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); - skb_pull(skb, l2_hdr_offset); skb->protocol = eth_type_trans(skb, netdev); @@ -1700,8 +1697,6 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); - skb->truesize = skb->len + sizeof(struct sk_buff); - if (!qlcnic_check_loopback_buff(skb->data)) adapter->diag_cnt++; diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index bf6d87adda4f..66eea5972020 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -1983,8 +1983,6 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) struct qlcnic_adapter *adapter = netdev_priv(netdev); struct net_device_stats *stats = &netdev->stats; - memset(stats, 0, sizeof(*stats)); - stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes; @@ -2190,9 +2188,16 @@ static int qlcnic_rx_poll(struct napi_struct *napi, int budget) #ifdef CONFIG_NET_POLL_CONTROLLER static void qlcnic_poll_controller(struct net_device *netdev) { + int ring; + struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_adapter *adapter = netdev_priv(netdev); + struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; + disable_irq(adapter->irq); - qlcnic_intr(adapter->irq, adapter); + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + qlcnic_intr(adapter->irq, sds_ring); + } enable_irq(adapter->irq); } #endif diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8d63f69b27d9..5f89e83501f4 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3919,12 +3919,12 @@ static int ql_adapter_down(struct ql_adapter *qdev) for (i = 0; i < qdev->rss_ring_count; i++) netif_napi_del(&qdev->rx_ring[i].napi); - ql_free_rx_buffers(qdev); - status = ql_adapter_reset(qdev); if (status) netif_err(qdev, ifdown, qdev->ndev, "reset(func #%d) FAILED!\n", qdev->func); + ql_free_rx_buffers(qdev); + return status; } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 078bbf4e6f19..992db2fa136e 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1212,7 +1212,8 @@ static void rtl8169_update_counters(struct net_device *dev) if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) return; - counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr); + counters = dma_alloc_coherent(&tp->pci_dev->dev, sizeof(*counters), + &paddr, GFP_KERNEL); if (!counters) return; @@ -1233,7 +1234,8 @@ static void rtl8169_update_counters(struct net_device *dev) RTL_W32(CounterAddrLow, 0); RTL_W32(CounterAddrHigh, 0); - pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr); + dma_free_coherent(&tp->pci_dev->dev, sizeof(*counters), counters, + paddr); } static void rtl8169_get_ethtool_stats(struct net_device *dev, @@ -2934,7 +2936,7 @@ static const struct rtl_cfg_info { .hw_start = rtl_hw_start_8168, .region = 2, .align = 8, - .intr_event = SYSErr | LinkChg | RxOverflow | + .intr_event = SYSErr | RxFIFOOver | LinkChg | RxOverflow | TxErr | TxOK | RxOK | RxErr, .napi_event = TxErr | TxOK | RxOK | RxOverflow, .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, @@ -3292,15 +3294,15 @@ static int rtl8169_open(struct net_device *dev) /* * Rx and Tx desscriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. + * dma_alloc_coherent provides more. */ - tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr); + tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, + &tp->TxPhyAddr, GFP_KERNEL); if (!tp->TxDescArray) goto err_pm_runtime_put; - tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr); + tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, + &tp->RxPhyAddr, GFP_KERNEL); if (!tp->RxDescArray) goto err_free_tx_0; @@ -3334,12 +3336,12 @@ out: err_release_ring_2: rtl8169_rx_clear(tp); err_free_rx_1: - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, + tp->RxPhyAddr); tp->RxDescArray = NULL; err_free_tx_0: - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, + tp->TxPhyAddr); tp->TxDescArray = NULL; err_pm_runtime_put: pm_runtime_put_noidle(&pdev->dev); @@ -3975,7 +3977,7 @@ static void rtl8169_free_rx_skb(struct rtl8169_private *tp, { struct pci_dev *pdev = tp->pci_dev; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), tp->rx_buf_sz, + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(*sk_buff); *sk_buff = NULL; @@ -4000,7 +4002,7 @@ static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev, struct RxDesc *desc, int rx_buf_sz, - unsigned int align) + unsigned int align, gfp_t gfp) { struct sk_buff *skb; dma_addr_t mapping; @@ -4008,13 +4010,13 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, pad = align ? align : NET_IP_ALIGN; - skb = netdev_alloc_skb(dev, rx_buf_sz + pad); + skb = __netdev_alloc_skb(dev, rx_buf_sz + pad, gfp); if (!skb) goto err_out; skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); - mapping = pci_map_single(pdev, skb->data, rx_buf_sz, + mapping = dma_map_single(&pdev->dev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); rtl8169_map_to_asic(desc, mapping, rx_buf_sz); @@ -4039,7 +4041,7 @@ static void rtl8169_rx_clear(struct rtl8169_private *tp) } static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, - u32 start, u32 end) + u32 start, u32 end, gfp_t gfp) { u32 cur; @@ -4054,7 +4056,7 @@ static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev, skb = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->RxDescArray + i, - tp->rx_buf_sz, tp->align); + tp->rx_buf_sz, tp->align, gfp); if (!skb) break; @@ -4082,7 +4084,7 @@ static int rtl8169_init_ring(struct net_device *dev) memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC) + if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC, GFP_KERNEL) != NUM_RX_DESC) goto err_out; rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); @@ -4099,7 +4101,8 @@ static void rtl8169_unmap_tx_skb(struct pci_dev *pdev, struct ring_info *tx_skb, { unsigned int len = tx_skb->len; - pci_unmap_single(pdev, le64_to_cpu(desc->addr), len, PCI_DMA_TODEVICE); + dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, + PCI_DMA_TODEVICE); desc->opts1 = 0x00; desc->opts2 = 0x00; desc->addr = 0x00; @@ -4243,7 +4246,8 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, txd = tp->TxDescArray + entry; len = frag->size; addr = ((void *) page_address(frag->page)) + frag->page_offset; - mapping = pci_map_single(tp->pci_dev, addr, len, PCI_DMA_TODEVICE); + mapping = dma_map_single(&tp->pci_dev->dev, addr, len, + PCI_DMA_TODEVICE); /* anti gcc 2.95.3 bugware (sic) */ status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); @@ -4313,7 +4317,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->tx_skb[entry].skb = skb; } - mapping = pci_map_single(tp->pci_dev, skb->data, len, PCI_DMA_TODEVICE); + mapping = dma_map_single(&tp->pci_dev->dev, skb->data, len, + PCI_DMA_TODEVICE); tp->tx_skb[entry].len = len; txd->addr = cpu_to_le64(mapping); @@ -4477,8 +4482,8 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, if (!skb) goto out; - pci_dma_sync_single_for_cpu(tp->pci_dev, addr, pkt_size, - PCI_DMA_FROMDEVICE); + dma_sync_single_for_cpu(&tp->pci_dev->dev, addr, pkt_size, + PCI_DMA_FROMDEVICE); skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); *sk_buff = skb; done = true; @@ -4549,11 +4554,11 @@ static int rtl8169_rx_interrupt(struct net_device *dev, rtl8169_rx_csum(skb, desc); if (rtl8169_try_rx_copy(&skb, tp, pkt_size, addr)) { - pci_dma_sync_single_for_device(pdev, addr, + dma_sync_single_for_device(&pdev->dev, addr, pkt_size, PCI_DMA_FROMDEVICE); rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { - pci_unmap_single(pdev, addr, tp->rx_buf_sz, + dma_unmap_single(&pdev->dev, addr, tp->rx_buf_sz, PCI_DMA_FROMDEVICE); tp->Rx_skbuff[entry] = NULL; } @@ -4583,7 +4588,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; - delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); + delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, GFP_ATOMIC); if (!delta && count) netif_info(tp, intr, dev, "no Rx buffer allocated\n"); tp->dirty_rx += delta; @@ -4625,8 +4630,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) } /* Work around for rx fifo overflow */ - if (unlikely(status & RxFIFOOver) && - (tp->mac_version == RTL_GIGA_MAC_VER_11)) { + if (unlikely(status & RxFIFOOver)) { netif_stop_queue(dev); rtl8169_tx_timeout(dev); break; @@ -4770,10 +4774,10 @@ static int rtl8169_close(struct net_device *dev) free_irq(dev->irq, dev); - pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, + tp->RxPhyAddr); + dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, + tp->TxPhyAddr); tp->TxDescArray = NULL; tp->RxDescArray = NULL; diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 07eb884ff982..44150f2f7bfd 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -384,7 +384,7 @@ static void rionet_remove(struct rio_dev *rdev) free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0); unregister_netdev(ndev); - kfree(ndev); + free_netdev(ndev); list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { list_del(&peer->node); diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index cc4bd8c65f8b..9265315baa0b 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c @@ -804,7 +804,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev) err_out_free_page: free_page((unsigned long) sp->srings); err_out_free_dev: - kfree(dev); + free_netdev(dev); err_out: return err; diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index f5a9eb1df593..79fd02bc69fd 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -1437,7 +1437,7 @@ static const struct net_device_ops sh_eth_netdev_ops = { static int sh_eth_drv_probe(struct platform_device *pdev) { - int ret, i, devno = 0; + int ret, devno = 0; struct resource *res; struct net_device *ndev = NULL; struct sh_eth_private *mdp; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 40e5c46e7571..465ae7e84507 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -43,6 +43,7 @@ #include <linux/seq_file.h> #include <linux/mii.h> #include <linux/slab.h> +#include <linux/dmi.h> #include <asm/irq.h> #include "skge.h" @@ -3868,6 +3869,8 @@ static void __devinit skge_show_addr(struct net_device *dev) netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); } +static int only_32bit_dma; + static int __devinit skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -3889,7 +3892,7 @@ static int __devinit skge_probe(struct pci_dev *pdev, pci_set_master(pdev); - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { using_dac = 1; err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { @@ -4147,8 +4150,21 @@ static struct pci_driver skge_driver = { .shutdown = skge_shutdown, }; +static struct dmi_system_id skge_32bit_dma_boards[] = { + { + .ident = "Gigabyte nForce boards", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"), + DMI_MATCH(DMI_BOARD_NAME, "nForce"), + }, + }, + {} +}; + static int __init skge_init_module(void) { + if (dmi_check_system(skge_32bit_dma_boards)) + only_32bit_dma = 1; skge_debug_init(); return pci_register_driver(&skge_driver); } diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 0909ae934ad0..8150ba154116 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -58,6 +58,7 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(SMSC_DRV_VERSION); +MODULE_ALIAS("platform:smsc911x"); #if USE_DEBUG > 0 static int debug = 16; diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c index bbb7951b9c4c..ea0461eb2dbe 100644 --- a/drivers/net/stmmac/stmmac_main.c +++ b/drivers/net/stmmac/stmmac_main.c @@ -1865,15 +1865,15 @@ static int stmmac_resume(struct platform_device *pdev) if (!netif_running(dev)) return 0; - spin_lock(&priv->lock); - if (priv->shutdown) { /* Re-open the interface and re-init the MAC/DMA - and the rings. */ + and the rings (i.e. on hibernation stage) */ stmmac_open(dev); - goto out_resume; + return 0; } + spin_lock(&priv->lock); + /* Power Down bit, into the PM register, is cleared * automatically as soon as a magic packet or a Wake-up frame * is received. Anyway, it's better to manually clear @@ -1901,7 +1901,6 @@ static int stmmac_resume(struct platform_device *pdev) netif_start_queue(dev); -out_resume: spin_unlock(&priv->lock); return 0; } diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index bc3af78a869f..1ec4b9e0239a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4666,7 +4666,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) desc_idx, *post_ptr); drop_it_no_recycle: /* Other statistics kept track of by card. */ - tp->net_stats.rx_dropped++; + tp->rx_dropped++; goto next_pkt; } @@ -4726,7 +4726,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) if (len > (tp->dev->mtu + ETH_HLEN) && skb->protocol != htons(ETH_P_8021Q)) { dev_kfree_skb(skb); - goto next_pkt; + goto drop_it_no_recycle; } if (desc->type_flags & RXD_FLAG_VLAN && @@ -9240,6 +9240,8 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, stats->rx_missed_errors = old_stats->rx_missed_errors + get_stat64(&hw_stats->rx_discards); + stats->rx_dropped = tp->rx_dropped; + return stats; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 4937bd190964..be7ff138a7f9 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2759,7 +2759,7 @@ struct tg3 { /* begin "everything else" cacheline(s) section */ - struct rtnl_link_stats64 net_stats; + unsigned long rx_dropped; struct rtnl_link_stats64 net_stats_prev; struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index 5efa57757a2c..6888e3d41462 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -243,6 +243,7 @@ enum { NWayState = (1 << 14) | (1 << 13) | (1 << 12), NWayRestart = (1 << 12), NonselPortActive = (1 << 9), + SelPortActive = (1 << 8), LinkFailStatus = (1 << 2), NetCxnErr = (1 << 1), }; @@ -363,7 +364,9 @@ static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, }; /* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; -static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, }; +static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; +/* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */ +static u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; @@ -1064,6 +1067,9 @@ static void de21041_media_timer (unsigned long data) unsigned int carrier; unsigned long flags; + /* clear port active bits */ + dw32(SIAStatus, NonselPortActive | SelPortActive); + carrier = (status & NetCxnErr) ? 0 : 1; if (carrier) { @@ -1158,14 +1164,29 @@ no_link_yet: static void de_media_interrupt (struct de_private *de, u32 status) { if (status & LinkPass) { + /* Ignore if current media is AUI or BNC and we can't use TP */ + if ((de->media_type == DE_MEDIA_AUI || + de->media_type == DE_MEDIA_BNC) && + (de->media_lock || + !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))) + return; + /* If current media is not TP, change it to TP */ + if ((de->media_type == DE_MEDIA_AUI || + de->media_type == DE_MEDIA_BNC)) { + de->media_type = DE_MEDIA_TP_AUTO; + de_stop_rxtx(de); + de_set_media(de); + de_start_rxtx(de); + } de_link_up(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); return; } BUG_ON(!(status & LinkFail)); - - if (netif_carrier_ok(de->dev)) { + /* Mark the link as down only if current media is TP */ + if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI && + de->media_type != DE_MEDIA_BNC) { de_link_down(de); mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); } @@ -1229,6 +1250,7 @@ static void de_adapter_sleep (struct de_private *de) if (de->de21040) return; + dw32(CSR13, 0); /* Reset phy */ pci_read_config_dword(de->pdev, PCIPM, &pmctl); pmctl |= PM_Sleep; pci_write_config_dword(de->pdev, PCIPM, pmctl); @@ -1574,12 +1596,15 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) return 0; /* nothing to change */ de_link_down(de); + mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); de_stop_rxtx(de); de->media_type = new_media; de->media_lock = media_lock; de->media_advertise = ecmd->advertising; de_set_media(de); + if (netif_running(de->dev)) + de_start_rxtx(de); return 0; } @@ -1911,8 +1936,14 @@ fill_defaults: for (i = 0; i < DE_MAX_MEDIA; i++) { if (de->media[i].csr13 == 0xffff) de->media[i].csr13 = t21041_csr13[i]; - if (de->media[i].csr14 == 0xffff) - de->media[i].csr14 = t21041_csr14[i]; + if (de->media[i].csr14 == 0xffff) { + /* autonegotiation is broken at least on some chip + revisions - rev. 0x21 works, 0x11 does not */ + if (de->pdev->revision < 0x20) + de->media[i].csr14 = t21041_csr14_brk[i]; + else + de->media[i].csr14 = t21041_csr14[i]; + } if (de->media[i].csr15 == 0xffff) de->media[i].csr15 = t21041_csr15[i]; } @@ -2158,6 +2189,8 @@ static int de_resume (struct pci_dev *pdev) dev_err(&dev->dev, "pci_enable_device failed in resume\n"); goto out; } + pci_set_master(pdev); + de_init_rings(de); de_init_hw(de); out_attach: netif_device_attach(dev); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 6efca66b8766..1cd752f9a6e1 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1652,6 +1652,8 @@ static int hso_get_count(struct hso_serial *serial, struct uart_icount cnow; struct hso_tiocmget *tiocmget = serial->tiocmget; + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + if (!tiocmget) return -ENOENT; spin_lock_irq(&serial->serial_lock); diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 08e7b6abacdd..b2bcf99e6f08 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -58,6 +58,7 @@ #define USB_PRODUCT_IPHONE 0x1290 #define USB_PRODUCT_IPHONE_3G 0x1292 #define USB_PRODUCT_IPHONE_3GS 0x1294 +#define USB_PRODUCT_IPHONE_4 0x1297 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -92,6 +93,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_3GS, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); @@ -424,10 +429,6 @@ static const struct net_device_ops ipheth_netdev_ops = { .ndo_get_stats = &ipheth_stats, }; -static struct device_type ipheth_type = { - .name = "wwan", -}; - static int ipheth_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -445,7 +446,7 @@ static int ipheth_probe(struct usb_interface *intf, netdev->netdev_ops = &ipheth_netdev_ops; netdev->watchdog_timeo = IPHETH_TX_TIMEOUT; - strcpy(netdev->name, "wwan%d"); + strcpy(netdev->name, "eth%d"); dev = netdev_priv(netdev); dev->udev = udev; @@ -495,7 +496,6 @@ static int ipheth_probe(struct usb_interface *intf, SET_NETDEV_DEV(netdev, &intf->dev); SET_ETHTOOL_OPS(netdev, &ops); - SET_NETDEV_DEVTYPE(netdev, &ipheth_type); retval = register_netdev(netdev); if (retval) { diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index fd69095ef6e3..f53412368ce1 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2824,7 +2824,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT); dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | - NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG; + NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM; ret = register_netdev(dev); if (ret < 0) diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 8cc9e319f435..1737d1488b35 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c @@ -1244,16 +1244,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) int i, result; struct device *dev = i2400m_dev(i2400m); const struct i2400m_msg_hdr *msg_hdr; - size_t pl_itr, pl_size, skb_len; + size_t pl_itr, pl_size; unsigned long flags; - unsigned num_pls, single_last; + unsigned num_pls, single_last, skb_len; skb_len = skb->len; - d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n", + d_fnstart(4, dev, "(i2400m %p skb %p [size %u])\n", i2400m, skb, skb_len); result = -EIO; msg_hdr = (void *) skb->data; - result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len); + result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb_len); if (result < 0) goto error_msg_hdr_check; result = -EIO; @@ -1261,10 +1261,10 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ num_pls * sizeof(msg_hdr->pld[0]); pl_itr = ALIGN(pl_itr, I2400M_PL_ALIGN); - if (pl_itr > skb->len) { /* got all the payload descriptors? */ + if (pl_itr > skb_len) { /* got all the payload descriptors? */ dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " "%u payload descriptors (%zu each, total %zu)\n", - skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); + skb_len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); goto error_pl_descr_short; } /* Walk each payload payload--check we really got it */ @@ -1272,7 +1272,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) /* work around old gcc warnings */ pl_size = i2400m_pld_size(&msg_hdr->pld[i]); result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i], - pl_itr, skb->len); + pl_itr, skb_len); if (result < 0) goto error_pl_descr_check; single_last = num_pls == 1 || i == num_pls - 1; @@ -1290,16 +1290,16 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) if (i < i2400m->rx_pl_min) i2400m->rx_pl_min = i; i2400m->rx_num++; - i2400m->rx_size_acc += skb->len; - if (skb->len < i2400m->rx_size_min) - i2400m->rx_size_min = skb->len; - if (skb->len > i2400m->rx_size_max) - i2400m->rx_size_max = skb->len; + i2400m->rx_size_acc += skb_len; + if (skb_len < i2400m->rx_size_min) + i2400m->rx_size_min = skb_len; + if (skb_len > i2400m->rx_size_max) + i2400m->rx_size_max = skb_len; spin_unlock_irqrestore(&i2400m->rx_lock, flags); error_pl_descr_check: error_pl_descr_short: error_msg_hdr_check: - d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n", + d_fnend(4, dev, "(i2400m %p skb %p [size %u]) = %d\n", i2400m, skb, skb_len, result); return result; } diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index a105087af963..f9aa1bc0a947 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -732,7 +732,7 @@ static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) /* Nothing to do for ADMtek BBP */ } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK) - wiphy_debug(dev->wiphy, "unsupported bbp type %d\n", + wiphy_debug(dev->wiphy, "unsupported BBP type %d\n", priv->bbp_type); ADM8211_RESTORE(); @@ -1032,7 +1032,7 @@ static int adm8211_hw_init_bbp(struct ieee80211_hw *dev) break; } } else - wiphy_debug(dev->wiphy, "unsupported bbp %d\n", priv->bbp_type); + wiphy_debug(dev->wiphy, "unsupported BBP %d\n", priv->bbp_type); ADM8211_CSR_WRITE(SYNRF, 0); @@ -1525,7 +1525,7 @@ static int adm8211_start(struct ieee80211_hw *dev) retval = request_irq(priv->pdev->irq, adm8211_interrupt, IRQF_SHARED, "adm8211", dev); if (retval) { - wiphy_err(dev->wiphy, "failed to register irq handler\n"); + wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); goto fail; } @@ -1902,7 +1902,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, goto err_free_eeprom; } - wiphy_info(dev->wiphy, "hwaddr %pm, rev 0x%02x\n", + wiphy_info(dev->wiphy, "hwaddr %pM, Rev 0x%02x\n", dev->wiphy->perm_addr, pdev->revision); return 0; diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index d5140a87f073..1128fa8c9ed5 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -655,7 +655,7 @@ static int at76_get_hw_config(struct at76_priv *priv) exit: kfree(hwcfg); if (ret < 0) - wiphy_err(priv->hw->wiphy, "cannot get hw config (error %d)\n", + wiphy_err(priv->hw->wiphy, "cannot get HW Config (error %d)\n", ret); return ret; @@ -960,7 +960,7 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv) sizeof(struct mib_mac_addr)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac_addr) failed: %d\n", ret); + "at76_get_mib (MAC_ADDR) failed: %d\n", ret); goto exit; } @@ -989,7 +989,7 @@ static void at76_dump_mib_mac_wep(struct at76_priv *priv) sizeof(struct mib_mac_wep)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac_wep) failed: %d\n", ret); + "at76_get_mib (MAC_WEP) failed: %d\n", ret); goto exit; } @@ -1026,7 +1026,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) sizeof(struct mib_mac_mgmt)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac_mgmt) failed: %d\n", ret); + "at76_get_mib (MAC_MGMT) failed: %d\n", ret); goto exit; } @@ -1062,7 +1062,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mac) failed: %d\n", ret); + "at76_get_mib (MAC) failed: %d\n", ret); goto exit; } @@ -1099,7 +1099,7 @@ static void at76_dump_mib_phy(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (phy) failed: %d\n", ret); + "at76_get_mib (PHY) failed: %d\n", ret); goto exit; } @@ -1132,7 +1132,7 @@ static void at76_dump_mib_local(struct at76_priv *priv) ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (local) failed: %d\n", ret); + "at76_get_mib (LOCAL) failed: %d\n", ret); goto exit; } @@ -1158,7 +1158,7 @@ static void at76_dump_mib_mdomain(struct at76_priv *priv) sizeof(struct mib_mdomain)); if (ret < 0) { wiphy_err(priv->hw->wiphy, - "at76_get_mib (mdomain) failed: %d\n", ret); + "at76_get_mib (MDOMAIN) failed: %d\n", ret); goto exit; } @@ -1229,7 +1229,7 @@ static int at76_submit_rx_urb(struct at76_priv *priv) struct sk_buff *skb = priv->rx_skb; if (!priv->rx_urb) { - wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is null\n", + wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is NULL\n", __func__); return -EFAULT; } @@ -1792,7 +1792,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) wiphy_err(priv->hw->wiphy, "error in tx submit urb: %d\n", ret); if (ret == -EINVAL) wiphy_err(priv->hw->wiphy, - "-einval: tx urb %p hcpriv %p complete %p\n", + "-EINVAL: tx urb %p hcpriv %p complete %p\n", priv->tx_urb, priv->tx_urb->hcpriv, priv->tx_urb->complete); } @@ -2310,7 +2310,7 @@ static int at76_init_new_device(struct at76_priv *priv, priv->mac80211_registered = 1; - wiphy_info(priv->hw->wiphy, "usb %s, mac %pm, firmware %d.%d.%d-%d\n", + wiphy_info(priv->hw->wiphy, "USB %s, MAC %pM, firmware %d.%d.%d-%d\n", dev_name(&interface->dev), priv->mac_addr, priv->fw_version.major, priv->fw_version.minor, priv->fw_version.patch, priv->fw_version.build); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c67b05f3bcbd..debfb0fbc7c5 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -245,7 +245,7 @@ static void __ar9170_dump_txstats(struct ar9170 *ar) { int i; - wiphy_debug(ar->hw->wiphy, "qos queue stats\n"); + wiphy_debug(ar->hw->wiphy, "QoS queue stats\n"); for (i = 0; i < __AR9170_NUM_TXQ; i++) wiphy_debug(ar->hw->wiphy, @@ -387,7 +387,7 @@ static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { #ifdef AR9170_QUEUE_DEBUG wiphy_debug(ar->hw->wiphy, - "skip frame => da %pm != %pm\n", + "skip frame => DA %pM != %pM\n", mac, ieee80211_get_DA(hdr)); ar9170_print_txheader(ar, skb); #endif /* AR9170_QUEUE_DEBUG */ diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 373dcfec689c..d77ce9906b6c 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1327,6 +1327,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, PCI_DMA_TODEVICE); rate = ieee80211_get_tx_rate(sc->hw, info); + if (!rate) { + ret = -EINVAL; + goto err_unmap; + } if (info->flags & IEEE80211_TX_CTL_NO_ACK) flags |= AR5K_TXDESC_NOACK; diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index cc648b6ae31c..a3d95cca8f0c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -543,7 +543,7 @@ static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) if (conf_is_ht40(conf)) return clockrate * 2; - return clockrate * 2; + return clockrate; } static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index b883b174385b..057fb69ddf7f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -797,7 +797,7 @@ static bool ar9300_uncompress_block(struct ath_hw *ah, length = block[it+1]; length &= 0xff; - if (length > 0 && spot >= 0 && spot+length < mdataSize) { + if (length > 0 && spot >= 0 && spot+length <= mdataSize) { ath_print(common, ATH_DBG_EEPROM, "Restore at %d: spot=%d " "offset=%d length=%d\n", diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 7f48df1e2903..0b09db0f8e7d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -62,7 +62,7 @@ #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 +#define CTL_MODE_M 0xf #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index a1c39526161a..345dd9721b41 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -31,7 +31,6 @@ enum ctl_group { #define NO_CTL 0xff #define SD_NO_CTL 0xE0 #define NO_CTL 0xff -#define CTL_MODE_M 7 #define CTL_11A 0 #define CTL_11B 1 #define CTL_11G 2 diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 1189dbb6e2a6..996e9d7d7586 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -2723,14 +2723,6 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv) packet = &priv->rx_buffers[i]; - /* Sync the DMA for the STATUS buffer so CPU is sure to get - * the correct values */ - pci_dma_sync_single_for_cpu(priv->pci_dev, - sq->nic + - sizeof(struct ipw2100_status) * i, - sizeof(struct ipw2100_status), - PCI_DMA_FROMDEVICE); - /* Sync the DMA for the RX buffer so CPU is sure to get * the correct values */ pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index fec026212326..0b779a41a142 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -265,7 +265,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 128, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -297,7 +297,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 128, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 6950a783913b..8ccfcd08218d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2731,7 +2731,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .tx_power_by_driver = true, }; @@ -2752,7 +2752,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .led_compensation = 64, .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .tx_power_by_driver = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d6da356608fa..d92b72909233 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2322,7 +2322,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .led_compensation = 61, .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .temperature_kelvin = true, .max_event_log_size = 512, .tx_power_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index aacf3770f075..48bdcd8d2e94 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -510,7 +510,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -541,7 +541,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -570,7 +570,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -601,7 +601,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -632,7 +632,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -663,7 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -693,7 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index af4fd50f3405..cee06b968de8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -388,7 +388,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -424,7 +424,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -459,7 +459,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -496,7 +496,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -532,7 +532,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -570,7 +570,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -606,7 +606,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -644,7 +644,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -680,7 +680,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, .max_event_log_size = 512, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, @@ -721,7 +721,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -756,7 +756,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -791,7 +791,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -828,7 +828,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -866,7 +866,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -902,7 +902,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, @@ -940,7 +940,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, - .monitor_recover_period = IWL_MONITORING_PERIOD, + .monitor_recover_period = IWL_DEF_MONITORING_PERIOD, .max_event_log_size = 1024, .ucode_tracing = true, .sensitivity_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9dd9e64c2b0b..8fd00a6e5120 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1411,7 +1411,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) clear_bit(STATUS_SCAN_HW, &priv->status); clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->abort_scan); } int iwlagn_manage_ibss_station(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c1882fd8345d..10d7b9b7f064 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3667,6 +3667,49 @@ out_exit: IWL_DEBUG_MAC80211(priv, "leave\n"); } +static void iwlagn_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct iwl_priv *priv = hw->priv; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) + + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); + +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + iwlcore_commit_rxon(priv); + + mutex_unlock(&priv->mutex); + + /* + * Receiving all multicast frames is always enabled by the + * default flags setup in iwl_connection_init_rx_config() + * since we currently do not support programming multicast + * filters into the device. + */ + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} + static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop) { struct iwl_priv *priv = hw->priv; @@ -3867,7 +3910,7 @@ static struct ieee80211_ops iwl_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, + .configure_filter = iwlagn_configure_filter, .set_key = iwl_mac_set_key, .update_tkip_key = iwl_mac_update_tkip_key, .conf_tx = iwl_mac_conf_tx, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2c03c6e20a72..e23c4060a0f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1328,51 +1328,6 @@ out: EXPORT_SYMBOL(iwl_apm_init); - -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct iwl_priv *priv = hw->priv; - __le32 filter_or = 0, filter_nand = 0; - -#define CHK(test, flag) do { \ - if (*total_flags & (test)) \ - filter_or |= (flag); \ - else \ - filter_nand |= (flag); \ - } while (0) - - IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", - changed_flags, *total_flags); - - CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); - CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); - CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); - -#undef CHK - - mutex_lock(&priv->mutex); - - priv->staging_rxon.filter_flags &= ~filter_nand; - priv->staging_rxon.filter_flags |= filter_or; - - iwlcore_commit_rxon(priv); - - mutex_unlock(&priv->mutex); - - /* - * Receiving all multicast frames is always enabled by the - * default flags setup in iwl_connection_init_rx_config() - * since we currently do not support programming multicast - * filters into the device. - */ - *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -} -EXPORT_SYMBOL(iwl_configure_filter); - int iwl_set_hw_params(struct iwl_priv *priv) { priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; @@ -2658,6 +2613,11 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EINVAL; + if (test_bit(STATUS_SCANNING, &priv->status)) { + IWL_DEBUG_INFO(priv, "scan in progress.\n"); + return -EINVAL; + } + if (mode >= IWL_MAX_FORCE_RESET) { IWL_DEBUG_INFO(priv, "invalid reset request.\n"); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4a71dfb10a15..5e6ee3da6bbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -372,9 +372,6 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, u32 decrypt_res, struct ieee80211_rx_status *stats); void iwl_irq_handle_error(struct iwl_priv *priv); -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast); int iwl_set_hw_params(struct iwl_priv *priv); void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl_bss_info_changed(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f35bcad56e36..2e97cd2fa98a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1049,7 +1049,8 @@ struct iwl_event_log { #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) /* timer constants use to monitor and recover stuck tx queues in mSecs */ -#define IWL_MONITORING_PERIOD (1000) +#define IWL_DEF_MONITORING_PERIOD (1000) +#define IWL_LONG_MONITORING_PERIOD (5000) #define IWL_ONE_HUNDRED_MSECS (100) #define IWL_SIXTY_SECS (60000) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 70c4b8fba0ee..d31661c1ce77 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3018,7 +3018,7 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); + queue_work(priv->workqueue, &priv->abort_scan); } static void iwl3945_bg_restart(struct work_struct *data) @@ -3391,6 +3391,55 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, return 0; } + +static void iwl3945_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + u64 multicast) +{ + struct iwl_priv *priv = hw->priv; + __le32 filter_or = 0, filter_nand = 0; + +#define CHK(test, flag) do { \ + if (*total_flags & (test)) \ + filter_or |= (flag); \ + else \ + filter_nand |= (flag); \ + } while (0) + + IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", + changed_flags, *total_flags); + + CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK); + CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK); + CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK); + +#undef CHK + + mutex_lock(&priv->mutex); + + priv->staging_rxon.filter_flags &= ~filter_nand; + priv->staging_rxon.filter_flags |= filter_or; + + /* + * Committing directly here breaks for some reason, + * but we'll eventually commit the filter flags + * change anyway. + */ + + mutex_unlock(&priv->mutex); + + /* + * Receiving all multicast frames is always enabled by the + * default flags setup in iwl_connection_init_rx_config() + * since we currently do not support programming multicast + * filters into the device. + */ + *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | + FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; +} + + /***************************************************************************** * * sysfs attributes @@ -3796,7 +3845,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { .add_interface = iwl_mac_add_interface, .remove_interface = iwl_mac_remove_interface, .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, + .configure_filter = iwl3945_configure_filter, .set_key = iwl3945_mac_set_key, .conf_tx = iwl_mac_conf_tx, .reset_tsf = iwl_mac_reset_tsf, diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index ba854c70ab94..87b634978b35 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -128,7 +128,7 @@ struct if_sdio_card { bool helper_allocated; bool firmware_allocated; - u8 buffer[65536]; + u8 buffer[65536] __attribute__((aligned(4))); spinlock_t lock; struct if_sdio_packet *packets; diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 01ad7f77383a..86fa8abdd66f 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -486,7 +486,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, struct ieee80211_rx_status rx_status; if (data->idle) { - wiphy_debug(hw->wiphy, "trying to tx when idle - reject\n"); + wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); return false; } diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index d761ed2d8af4..f152a25be59f 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -910,14 +910,14 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma); if (rxq->rxd == NULL) { - wiphy_err(hw->wiphy, "failed to alloc rx descriptors\n"); + wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n"); return -ENOMEM; } memset(rxq->rxd, 0, size); rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL); if (rxq->buf == NULL) { - wiphy_err(hw->wiphy, "failed to alloc rx skbuff list\n"); + wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n"); pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma); return -ENOMEM; } @@ -1145,14 +1145,14 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma); if (txq->txd == NULL) { - wiphy_err(hw->wiphy, "failed to alloc tx descriptors\n"); + wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n"); return -ENOMEM; } memset(txq->txd, 0, size); txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL); if (txq->skb == NULL) { - wiphy_err(hw->wiphy, "failed to alloc tx skbuff list\n"); + wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n"); pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma); return -ENOMEM; } @@ -1573,7 +1573,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) PCI_DMA_BIDIRECTIONAL); if (!timeout) { - wiphy_err(hw->wiphy, "command %s timeout after %u ms\n", + wiphy_err(hw->wiphy, "Command %s timeout after %u ms\n", mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), MWL8K_CMD_TIMEOUT_MS); rc = -ETIMEDOUT; @@ -1584,11 +1584,11 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) rc = cmd->result ? -EINVAL : 0; if (rc) - wiphy_err(hw->wiphy, "command %s error 0x%x\n", + wiphy_err(hw->wiphy, "Command %s error 0x%x\n", mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), le16_to_cpu(cmd->result)); else if (ms > 2000) - wiphy_notice(hw->wiphy, "command %s took %d ms\n", + wiphy_notice(hw->wiphy, "Command %s took %d ms\n", mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), ms); @@ -3210,7 +3210,7 @@ static int mwl8k_start(struct ieee80211_hw *hw) rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { - wiphy_err(hw->wiphy, "failed to register irq handler\n"); + wiphy_err(hw->wiphy, "failed to register IRQ handler\n"); return -EIO; } @@ -3926,7 +3926,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, priv->sram = pci_iomap(pdev, 0, 0x10000); if (priv->sram == NULL) { - wiphy_err(hw->wiphy, "cannot map device sram\n"); + wiphy_err(hw->wiphy, "Cannot map device SRAM\n"); goto err_iounmap; } @@ -3938,7 +3938,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, if (priv->regs == NULL) { priv->regs = pci_iomap(pdev, 2, 0x10000); if (priv->regs == NULL) { - wiphy_err(hw->wiphy, "cannot map device registers\n"); + wiphy_err(hw->wiphy, "Cannot map device registers\n"); goto err_iounmap; } } @@ -3950,14 +3950,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Ask userland hotplug daemon for the device firmware */ rc = mwl8k_request_firmware(priv); if (rc) { - wiphy_err(hw->wiphy, "firmware files not found\n"); + wiphy_err(hw->wiphy, "Firmware files not found\n"); goto err_stop_firmware; } /* Load firmware into hardware */ rc = mwl8k_load_firmware(hw); if (rc) { - wiphy_err(hw->wiphy, "cannot start firmware\n"); + wiphy_err(hw->wiphy, "Cannot start firmware\n"); goto err_stop_firmware; } @@ -4047,7 +4047,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = request_irq(priv->pdev->irq, mwl8k_interrupt, IRQF_SHARED, MWL8K_NAME, hw); if (rc) { - wiphy_err(hw->wiphy, "failed to register irq handler\n"); + wiphy_err(hw->wiphy, "failed to register IRQ handler\n"); goto err_free_queues; } @@ -4067,7 +4067,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = mwl8k_cmd_get_hw_spec_sta(hw); } if (rc) { - wiphy_err(hw->wiphy, "cannot initialise firmware\n"); + wiphy_err(hw->wiphy, "Cannot initialise firmware\n"); goto err_free_irq; } @@ -4081,14 +4081,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, /* Turn radio off */ rc = mwl8k_cmd_radio_disable(hw); if (rc) { - wiphy_err(hw->wiphy, "cannot disable\n"); + wiphy_err(hw->wiphy, "Cannot disable\n"); goto err_free_irq; } /* Clear MAC address */ rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00"); if (rc) { - wiphy_err(hw->wiphy, "cannot clear mac address\n"); + wiphy_err(hw->wiphy, "Cannot clear MAC address\n"); goto err_free_irq; } @@ -4098,7 +4098,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, rc = ieee80211_register_hw(hw); if (rc) { - wiphy_err(hw->wiphy, "cannot register device\n"); + wiphy_err(hw->wiphy, "Cannot register device\n"); goto err_free_queues; } diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index d687cb7f2a59..78347041ec40 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -167,7 +167,7 @@ static int p54_generate_band(struct ieee80211_hw *dev, } if (j == 0) { - wiphy_err(dev->wiphy, "disabling totally damaged %d GHz band\n", + wiphy_err(dev->wiphy, "Disabling totally damaged %d GHz band\n", (band == IEEE80211_BAND_2GHZ) ? 2 : 5); ret = -ENODATA; @@ -695,12 +695,12 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) u8 perm_addr[ETH_ALEN]; wiphy_warn(dev->wiphy, - "invalid hwaddr! using randomly generated mac addr\n"); + "Invalid hwaddr! Using randomly generated MAC addr\n"); random_ether_addr(perm_addr); SET_IEEE80211_PERM_ADDR(dev, perm_addr); } - wiphy_info(dev->wiphy, "hwaddr %pm, mac:isl38%02x rf:%s\n", + wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n", dev->wiphy->perm_addr, priv->version, p54_rf_chips[priv->rxhw]); diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 47006bca4852..15b20c29a604 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -125,7 +125,7 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) if (fw_version) wiphy_info(priv->hw->wiphy, - "fw rev %s - softmac protocol %x.%x\n", + "FW rev %s - Softmac protocol %x.%x\n", fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); if (priv->fw_var < 0x500) diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c index ea91f5cce6b3..3837e1eec5f4 100644 --- a/drivers/net/wireless/p54/led.c +++ b/drivers/net/wireless/p54/led.c @@ -58,7 +58,7 @@ static void p54_update_leds(struct work_struct *work) err = p54_set_leds(priv); if (err && net_ratelimit()) wiphy_err(priv->hw->wiphy, - "failed to update leds (%d).\n", err); + "failed to update LEDs (%d).\n", err); if (rerun) ieee80211_queue_delayed_work(priv->hw, &priv->led_work, @@ -103,7 +103,7 @@ static int p54_register_led(struct p54_common *priv, err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev); if (err) wiphy_err(priv->hw->wiphy, - "failed to register %s led.\n", name); + "Failed to register %s LED.\n", name); else led->registered = 1; diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 822f8dc26e9c..1eacba4daa5b 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -466,7 +466,7 @@ static int p54p_open(struct ieee80211_hw *dev) P54P_READ(dev_int); if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - wiphy_err(dev->wiphy, "cannot boot firmware!\n"); + wiphy_err(dev->wiphy, "Cannot boot firmware!\n"); p54p_stop(dev); return -ETIMEDOUT; } diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 427b46f558ed..0e937dc0c9c4 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -446,7 +446,7 @@ static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (!payload->status)) + !(payload->status & P54_TX_FAILED)) info->flags |= IEEE80211_TX_STAT_ACK; if (payload->status & P54_TX_PSM_CANCELLED) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; @@ -540,7 +540,7 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) case P54_TRAP_BEACON_TX: break; case P54_TRAP_RADAR: - wiphy_info(priv->hw->wiphy, "radar (freq:%d mhz)\n", freq); + wiphy_info(priv->hw->wiphy, "radar (freq:%d MHz)\n", freq); break; case P54_TRAP_NO_BEACON: if (priv->vif) diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index b50c39aaec05..30107ce78dfb 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -445,7 +445,7 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) &priv->rx_ring_dma); if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { - wiphy_err(dev->wiphy, "cannot allocate rx ring\n"); + wiphy_err(dev->wiphy, "Cannot allocate RX ring\n"); return -ENOMEM; } @@ -502,7 +502,7 @@ static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); if (!ring || (unsigned long)ring & 0xFF) { - wiphy_err(dev->wiphy, "cannot allocate tx ring (prio = %d)\n", + wiphy_err(dev->wiphy, "Cannot allocate TX ring (prio = %d)\n", prio); return -ENOMEM; } @@ -568,7 +568,7 @@ static int rtl8180_start(struct ieee80211_hw *dev) ret = request_irq(priv->pdev->irq, rtl8180_interrupt, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) { - wiphy_err(dev->wiphy, "failed to register irq handler\n"); + wiphy_err(dev->wiphy, "failed to register IRQ handler\n"); goto err_free_rings; } diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 5738a55c1b06..98e0351c1dd6 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -573,7 +573,7 @@ static int rtl8187_cmd_reset(struct ieee80211_hw *dev) } while (--i); if (!i) { - wiphy_err(dev->wiphy, "reset timeout!\n"); + wiphy_err(dev->wiphy, "Reset timeout!\n"); return -ETIMEDOUT; } @@ -1526,7 +1526,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, mutex_init(&priv->conf_mutex); skb_queue_head_init(&priv->b_tx_status.queue); - wiphy_info(dev->wiphy, "hwaddr %pm, %s v%d + %s, rfkill mask %d\n", + wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n", mac_addr, chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c index fd96f9112322..97eebdcf7eb9 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c @@ -366,7 +366,7 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev) rtl8225_write(dev, 0x02, 0x044d); msleep(100); if (!(rtl8225_read(dev, 6) & (1 << 7))) - wiphy_warn(dev->wiphy, "rf calibration failed! %x\n", + wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", rtl8225_read(dev, 6)); } @@ -735,7 +735,7 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev) rtl8225_write(dev, 0x02, 0x044D); msleep(100); if (!(rtl8225_read(dev, 6) & (1 << 7))) - wiphy_warn(dev->wiphy, "rf calibration failed! %x\n", + wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n", rtl8225_read(dev, 6)); } diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index a9352b2c7ac4..b7e755f4178a 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c @@ -141,16 +141,6 @@ static struct notifier_block module_load_nb = { .notifier_call = module_load_notify, }; - -static void end_sync(void) -{ - end_cpu_work(); - /* make sure we don't leak task structs */ - process_task_mortuary(); - process_task_mortuary(); -} - - int sync_start(void) { int err; @@ -158,7 +148,7 @@ int sync_start(void) if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) return -ENOMEM; - start_cpu_work(); + mutex_lock(&buffer_mutex); err = task_handoff_register(&task_free_nb); if (err) @@ -173,7 +163,10 @@ int sync_start(void) if (err) goto out4; + start_cpu_work(); + out: + mutex_unlock(&buffer_mutex); return err; out4: profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); @@ -182,7 +175,6 @@ out3: out2: task_handoff_unregister(&task_free_nb); out1: - end_sync(); free_cpumask_var(marked_cpus); goto out; } @@ -190,11 +182,20 @@ out1: void sync_stop(void) { + /* flush buffers */ + mutex_lock(&buffer_mutex); + end_cpu_work(); unregister_module_notifier(&module_load_nb); profile_event_unregister(PROFILE_MUNMAP, &munmap_nb); profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb); task_handoff_unregister(&task_free_nb); - end_sync(); + mutex_unlock(&buffer_mutex); + flush_scheduled_work(); + + /* make sure we don't leak task structs */ + process_task_mortuary(); + process_task_mortuary(); + free_cpumask_var(marked_cpus); } diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 219f79e2210a..f179ac2ea801 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -120,8 +120,6 @@ void end_cpu_work(void) cancel_delayed_work(&b->work); } - - flush_scheduled_work(); } /* diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 45fcc1e96df9..3bc72d18b121 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -338,9 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) acpi_handle chandle, handle; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; - flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | - OSC_SHPC_NATIVE_HP_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + flags &= OSC_SHPC_NATIVE_HP_CONTROL; if (!flags) { err("Invalid flags %u specified!\n", flags); return -EINVAL; @@ -360,7 +358,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); dbg("Trying to get hotplug control for %s\n", (char *)string.pointer); - status = acpi_pci_osc_control_set(handle, flags); + status = acpi_pci_osc_control_set(handle, &flags, flags); if (ACPI_SUCCESS(status)) goto got_one; if (status == AE_SUPPORT) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4ed76b47b6dc..73d513989263 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -176,19 +176,11 @@ static inline void pciehp_firmware_init(void) { pciehp_acpi_slot_detection_init(); } - -static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) -{ - int retval; - u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - retval = acpi_get_hp_hw_control_from_firmware(dev, flags); - if (retval) - return retval; - return pciehp_acpi_slot_detection_check(dev); -} #else #define pciehp_firmware_init() do {} while (0) -#define pciehp_get_hp_hw_control_from_firmware(dev) 0 +static inline int pciehp_acpi_slot_detection_check(struct pci_dev *dev) +{ + return 0; +} #endif /* CONFIG_ACPI */ #endif /* _PCIEHP_H */ diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 1f4000a5a108..2574700db461 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -85,9 +85,7 @@ static int __init dummy_probe(struct pcie_device *dev) acpi_handle handle; struct dummy_slot *slot, *tmp; struct pci_dev *pdev = dev->port; - /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ - if (pciehp_get_hp_hw_control_from_firmware(pdev)) - return -ENODEV; + pos = pci_pcie_cap(pdev); if (!pos) return -ENODEV; diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 3588ea61b0dd..aa5f3ff629ff 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -59,7 +59,7 @@ module_param(pciehp_force, bool, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); -MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); +MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if OSHP is missing"); #define PCIE_MODULE_NAME "pciehp" @@ -235,7 +235,7 @@ static int pciehp_probe(struct pcie_device *dev) dev_info(&dev->device, "Bypassing BIOS check for pciehp use on %s\n", pci_name(dev->port)); - else if (pciehp_get_hp_hw_control_from_firmware(dev->port)) + else if (pciehp_acpi_slot_detection_check(dev->port)) goto err_out_none; ctrl = pcie_init(dev); diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index c3ceebb5be84..4789f8e8bf7a 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -71,6 +71,49 @@ #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) #define DMA_64BIT_PFN IOVA_PFN(DMA_BIT_MASK(64)) +/* page table handling */ +#define LEVEL_STRIDE (9) +#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) + +static inline int agaw_to_level(int agaw) +{ + return agaw + 2; +} + +static inline int agaw_to_width(int agaw) +{ + return 30 + agaw * LEVEL_STRIDE; +} + +static inline int width_to_agaw(int width) +{ + return (width - 30) / LEVEL_STRIDE; +} + +static inline unsigned int level_to_offset_bits(int level) +{ + return (level - 1) * LEVEL_STRIDE; +} + +static inline int pfn_level_offset(unsigned long pfn, int level) +{ + return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; +} + +static inline unsigned long level_mask(int level) +{ + return -1UL << level_to_offset_bits(level); +} + +static inline unsigned long level_size(int level) +{ + return 1UL << level_to_offset_bits(level); +} + +static inline unsigned long align_to_level(unsigned long pfn, int level) +{ + return (pfn + level_size(level) - 1) & level_mask(level); +} /* VT-d pages must always be _smaller_ than MM pages. Otherwise things are never going to work. */ @@ -434,8 +477,6 @@ void free_iova_mem(struct iova *iova) } -static inline int width_to_agaw(int width); - static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw) { unsigned long sagaw; @@ -646,51 +687,6 @@ out: spin_unlock_irqrestore(&iommu->lock, flags); } -/* page table handling */ -#define LEVEL_STRIDE (9) -#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) - -static inline int agaw_to_level(int agaw) -{ - return agaw + 2; -} - -static inline int agaw_to_width(int agaw) -{ - return 30 + agaw * LEVEL_STRIDE; - -} - -static inline int width_to_agaw(int width) -{ - return (width - 30) / LEVEL_STRIDE; -} - -static inline unsigned int level_to_offset_bits(int level) -{ - return (level - 1) * LEVEL_STRIDE; -} - -static inline int pfn_level_offset(unsigned long pfn, int level) -{ - return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK; -} - -static inline unsigned long level_mask(int level) -{ - return -1UL << level_to_offset_bits(level); -} - -static inline unsigned long level_size(int level) -{ - return 1UL << level_to_offset_bits(level); -} - -static inline unsigned long align_to_level(unsigned long pfn, int level) -{ - return (pfn + level_size(level) - 1) & level_mask(level); -} - static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, unsigned long pfn) { @@ -3761,6 +3757,33 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); +#define GGC 0x52 +#define GGC_MEMORY_SIZE_MASK (0xf << 8) +#define GGC_MEMORY_SIZE_NONE (0x0 << 8) +#define GGC_MEMORY_SIZE_1M (0x1 << 8) +#define GGC_MEMORY_SIZE_2M (0x3 << 8) +#define GGC_MEMORY_VT_ENABLED (0x8 << 8) +#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8) +#define GGC_MEMORY_SIZE_3M_VT (0xa << 8) +#define GGC_MEMORY_SIZE_4M_VT (0xb << 8) + +static void __devinit quirk_calpella_no_shadow_gtt(struct pci_dev *dev) +{ + unsigned short ggc; + + if (pci_read_config_word(dev, GGC, &ggc)) + return; + + if (!(ggc & GGC_MEMORY_VT_ENABLED)) { + printk(KERN_INFO "DMAR: BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); + dmar_map_gfx = 0; + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt); + /* On Tylersburg chipsets, some BIOSes have been known to enable the ISOCH DMAR unit for the Azalia sound device, but not give it any TLB entries, which causes it to deadlock. Check for that. We do diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index ce6a3666b3d9..553d8ee55c1c 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -608,7 +608,7 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, * the VF BAR size multiplied by the number of VFs. The alignment * is just the VF BAR size. */ -int pci_sriov_resource_alignment(struct pci_dev *dev, int resno) +resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno) { struct resource tmp; enum pci_bar_type type; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 679c39de6a89..6beb11b617a9 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -140,8 +140,10 @@ static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } #ifdef CONFIG_PCIEAER void pci_no_aer(void); +bool pci_aer_available(void); #else static inline void pci_no_aer(void) { } +static inline bool pci_aer_available(void) { return false; } #endif static inline int pci_no_d1d2(struct pci_dev *dev) @@ -262,7 +264,8 @@ extern int pci_iov_init(struct pci_dev *dev); extern void pci_iov_release(struct pci_dev *dev); extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); -extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno); +extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, + int resno); extern void pci_restore_iov_state(struct pci_dev *dev); extern int pci_iov_bus_range(struct pci_bus *bus); @@ -318,7 +321,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev) } #endif /* CONFIG_PCI_IOV */ -static inline int pci_resource_alignment(struct pci_dev *dev, +static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, struct resource *res) { #ifdef CONFIG_PCI_IOV diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index ea654545e7c4..00c62df5a9fc 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile @@ -6,10 +6,11 @@ obj-$(CONFIG_PCIEASPM) += aspm.o pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o +pcieportdrv-$(CONFIG_ACPI) += portdrv_acpi.o obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o # Build PCI Express AER if needed obj-$(CONFIG_PCIEAER) += aer/ -obj-$(CONFIG_PCIE_PME) += pme/ +obj-$(CONFIG_PCIE_PME) += pme.o diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 484cc55194b8..f409948e1a9b 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -72,6 +72,11 @@ void pci_no_aer(void) pcie_aer_disable = 1; /* has priority over 'forceload' */ } +bool pci_aer_available(void) +{ + return !pcie_aer_disable && pci_msi_enabled(); +} + static int set_device_error_reporting(struct pci_dev *dev, void *data) { bool enable = *((bool *)data); @@ -411,9 +416,7 @@ static void aer_error_resume(struct pci_dev *dev) */ static int __init aer_service_init(void) { - if (pcie_aer_disable) - return -ENXIO; - if (!pci_msi_enabled()) + if (!pci_aer_available()) return -ENXIO; return pcie_port_service_register(&aerdriver); } diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index f278d7b0d95d..2bb9b8972211 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -19,42 +19,6 @@ #include <acpi/apei.h> #include "aerdrv.h" -/** - * aer_osc_setup - run ACPI _OSC method - * @pciedev: pcie_device which AER is being enabled on - * - * @return: Zero on success. Nonzero otherwise. - * - * Invoked when PCIe bus loads AER service driver. To avoid conflict with - * BIOS AER support requires BIOS to yield AER control to OS native driver. - **/ -int aer_osc_setup(struct pcie_device *pciedev) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *pdev = pciedev->port; - acpi_handle handle = NULL; - - if (acpi_pci_disabled) - return -1; - - handle = acpi_find_root_bridge_handle(pdev); - if (handle) { - status = acpi_pci_osc_control_set(handle, - OSC_PCI_EXPRESS_AER_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - } - - if (ACPI_FAILURE(status)) { - dev_printk(KERN_DEBUG, &pciedev->device, "AER service couldn't " - "init device: %s\n", - (status == AE_SUPPORT || status == AE_NOT_FOUND) ? - "no _OSC support" : "_OSC failed"); - return -1; - } - - return 0; -} - #ifdef CONFIG_ACPI_APEI static inline int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index fc0b5a93e1de..29e268fadf14 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -772,22 +772,10 @@ void aer_isr(struct work_struct *work) */ int aer_init(struct pcie_device *dev) { - if (pcie_aer_get_firmware_first(dev->port)) { - dev_printk(KERN_DEBUG, &dev->device, - "PCIe errors handled by platform firmware.\n"); - goto out; - } - - if (aer_osc_setup(dev)) - goto out; - - return 0; -out: if (forceload) { dev_printk(KERN_DEBUG, &dev->device, "aerdrv forceload requested.\n"); pcie_aer_force_firmware_first(dev->port, 0); - return 0; } - return -ENXIO; + return 0; } diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme.c index bbdea18693d9..2f3c90407227 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme.c @@ -23,38 +23,13 @@ #include <linux/pci-acpi.h> #include <linux/pm_runtime.h> -#include "../../pci.h" -#include "pcie_pme.h" +#include "../pci.h" +#include "portdrv.h" #define PCI_EXP_RTSTA_PME 0x10000 /* PME status */ #define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */ /* - * If set, this switch will prevent the PCIe root port PME service driver from - * being registered. Consequently, the interrupt-based PCIe PME signaling will - * not be used by any PCIe root ports in that case. - */ -static bool pcie_pme_disabled = true; - -/* - * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: - * "In order to maintain compatibility with non-PCI Express-aware system - * software, system power management logic must be configured by firmware to use - * the legacy mechanism of signaling PME by default. PCI Express-aware system - * software must notify the firmware prior to enabling native, interrupt-based - * PME signaling." However, if the platform doesn't provide us with a suitable - * notification mechanism or the notification fails, it is not clear whether or - * not we are supposed to use the interrupt-based PCIe PME signaling. The - * switch below can be used to indicate the desired behaviour. When set, it - * will make the kernel use the interrupt-based PCIe PME signaling regardless of - * the platform notification status, although the kernel will attempt to notify - * the platform anyway. When unset, it will prevent the kernel from using the - * the interrupt-based PCIe PME signaling if the platform notification fails, - * which is the default. - */ -static bool pcie_pme_force_enable; - -/* * If this switch is set, MSI will not be used for PCIe PME signaling. This * causes the PCIe port driver to use INTx interrupts only, but it turns out * that using MSI for PCIe PME signaling doesn't play well with PCIe PME-based @@ -64,38 +39,13 @@ bool pcie_pme_msi_disabled; static int __init pcie_pme_setup(char *str) { - if (!strncmp(str, "auto", 4)) - pcie_pme_disabled = false; - else if (!strncmp(str, "force", 5)) - pcie_pme_force_enable = true; - - str = strchr(str, ','); - if (str) { - str++; - str += strspn(str, " \t"); - if (*str && !strcmp(str, "nomsi")) - pcie_pme_msi_disabled = true; - } + if (!strncmp(str, "nomsi", 5)) + pcie_pme_msi_disabled = true; return 1; } __setup("pcie_pme=", pcie_pme_setup); -/** - * pcie_pme_platform_setup - Ensure that the kernel controls the PCIe PME. - * @srv: PCIe PME root port service to use for carrying out the check. - * - * Notify the platform that the native PCIe PME is going to be used and return - * 'true' if the control of the PCIe PME registers has been acquired from the - * platform. - */ -static bool pcie_pme_platform_setup(struct pcie_device *srv) -{ - if (!pcie_pme_platform_notify(srv)) - return true; - return pcie_pme_force_enable; -} - struct pcie_pme_service_data { spinlock_t lock; struct pcie_device *srv; @@ -108,7 +58,7 @@ struct pcie_pme_service_data { * @dev: PCIe root port or event collector. * @enable: Enable or disable the interrupt. */ -static void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) +void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable) { int rtctl_pos; u16 rtctl; @@ -417,9 +367,6 @@ static int pcie_pme_probe(struct pcie_device *srv) struct pcie_pme_service_data *data; int ret; - if (!pcie_pme_platform_setup(srv)) - return -EACCES; - data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -509,8 +456,7 @@ static struct pcie_port_service_driver pcie_pme_driver = { */ static int __init pcie_pme_service_init(void) { - return pcie_pme_disabled ? - -ENODEV : pcie_port_service_register(&pcie_pme_driver); + return pcie_port_service_register(&pcie_pme_driver); } module_init(pcie_pme_service_init); diff --git a/drivers/pci/pcie/pme/Makefile b/drivers/pci/pcie/pme/Makefile deleted file mode 100644 index 8b9238053080..000000000000 --- a/drivers/pci/pcie/pme/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for PCI-Express Root Port PME signaling driver -# - -obj-$(CONFIG_PCIE_PME) += pmedriver.o - -pmedriver-objs := pcie_pme.o -pmedriver-$(CONFIG_ACPI) += pcie_pme_acpi.o diff --git a/drivers/pci/pcie/pme/pcie_pme.h b/drivers/pci/pcie/pme/pcie_pme.h deleted file mode 100644 index b30d2b7c9775..000000000000 --- a/drivers/pci/pcie/pme/pcie_pme.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * drivers/pci/pcie/pme/pcie_pme.h - * - * PCI Express Root Port PME signaling support - * - * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. - */ - -#ifndef _PCIE_PME_H_ -#define _PCIE_PME_H_ - -struct pcie_device; - -#ifdef CONFIG_ACPI -extern int pcie_pme_acpi_setup(struct pcie_device *srv); - -static inline int pcie_pme_platform_notify(struct pcie_device *srv) -{ - return pcie_pme_acpi_setup(srv); -} -#else /* !CONFIG_ACPI */ -static inline int pcie_pme_platform_notify(struct pcie_device *srv) -{ - return 0; -} -#endif /* !CONFIG_ACPI */ - -#endif diff --git a/drivers/pci/pcie/pme/pcie_pme_acpi.c b/drivers/pci/pcie/pme/pcie_pme_acpi.c deleted file mode 100644 index 83ab2287ae3f..000000000000 --- a/drivers/pci/pcie/pme/pcie_pme_acpi.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * PCIe Native PME support, ACPI-related part - * - * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. - * - * This file is subject to the terms and conditions of the GNU General Public - * License V2. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/acpi.h> -#include <linux/pci-acpi.h> -#include <linux/pcieport_if.h> - -/** - * pcie_pme_acpi_setup - Request the ACPI BIOS to release control over PCIe PME. - * @srv - PCIe PME service for a root port or event collector. - * - * Invoked when the PCIe bus type loads PCIe PME service driver. To avoid - * conflict with the BIOS PCIe support requires the BIOS to yield PCIe PME - * control to the kernel. - */ -int pcie_pme_acpi_setup(struct pcie_device *srv) -{ - acpi_status status = AE_NOT_FOUND; - struct pci_dev *port = srv->port; - acpi_handle handle; - int error = 0; - - if (acpi_pci_disabled) - return -ENOSYS; - - dev_info(&port->dev, "Requesting control of PCIe PME from ACPI BIOS\n"); - - handle = acpi_find_root_bridge_handle(port); - if (!handle) - return -EINVAL; - - status = acpi_pci_osc_control_set(handle, - OSC_PCI_EXPRESS_PME_CONTROL | - OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); - if (ACPI_FAILURE(status)) { - dev_info(&port->dev, - "Failed to receive control of PCIe PME service: %s\n", - (status == AE_SUPPORT || status == AE_NOT_FOUND) ? - "no _OSC support" : "ACPI _OSC failed"); - error = -ENODEV; - } - - return error; -} diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 813a5c3427b6..7b5aba0a3291 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -20,6 +20,9 @@ #define get_descriptor_id(type, service) (((type - 4) << 4) | service) +extern bool pcie_ports_disabled; +extern bool pcie_ports_auto; + extern struct bus_type pcie_port_bus_type; extern int pcie_port_device_register(struct pci_dev *dev); #ifdef CONFIG_PM @@ -30,6 +33,8 @@ extern void pcie_port_device_remove(struct pci_dev *dev); extern int __must_check pcie_port_bus_register(void); extern void pcie_port_bus_unregister(void); +struct pci_dev; + #ifdef CONFIG_PCIE_PME extern bool pcie_pme_msi_disabled; @@ -42,9 +47,26 @@ static inline bool pcie_pme_no_msi(void) { return pcie_pme_msi_disabled; } + +extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable); #else /* !CONFIG_PCIE_PME */ static inline void pcie_pme_disable_msi(void) {} static inline bool pcie_pme_no_msi(void) { return false; } +static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {} #endif /* !CONFIG_PCIE_PME */ +#ifdef CONFIG_ACPI +extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask); + +static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) +{ + return pcie_port_acpi_setup(port, mask); +} +#else /* !CONFIG_ACPI */ +static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) +{ + return 0; +} +#endif /* !CONFIG_ACPI */ + #endif /* _PORTDRV_H_ */ diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c new file mode 100644 index 000000000000..b7c4cb1ccb23 --- /dev/null +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -0,0 +1,77 @@ +/* + * PCIe Port Native Services Support, ACPI-Related Part + * + * Copyright (C) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License V2. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/acpi.h> +#include <linux/pci-acpi.h> +#include <linux/pcieport_if.h> + +#include "aer/aerdrv.h" +#include "../pci.h" + +/** + * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services. + * @port: PCIe Port service for a root port or event collector. + * @srv_mask: Bit mask of services that can be enabled for @port. + * + * Invoked when @port is identified as a PCIe port device. To avoid conflicts + * with the BIOS PCIe port native services support requires the BIOS to yield + * control of these services to the kernel. The mask of services that the BIOS + * allows to be enabled for @port is written to @srv_mask. + * + * NOTE: It turns out that we cannot do that for individual port services + * separately, because that would make some systems work incorrectly. + */ +int pcie_port_acpi_setup(struct pci_dev *port, int *srv_mask) +{ + acpi_status status; + acpi_handle handle; + u32 flags; + + if (acpi_pci_disabled) + return 0; + + handle = acpi_find_root_bridge_handle(port); + if (!handle) + return -EINVAL; + + flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL + | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL + | OSC_PCI_EXPRESS_PME_CONTROL; + + if (pci_aer_available()) { + if (pcie_aer_get_firmware_first(port)) + dev_dbg(&port->dev, "PCIe errors handled by BIOS.\n"); + else + flags |= OSC_PCI_EXPRESS_AER_CONTROL; + } + + status = acpi_pci_osc_control_set(handle, &flags, + OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + if (ACPI_FAILURE(status)) { + dev_dbg(&port->dev, "ACPI _OSC request failed (code %d)\n", + status); + return -ENODEV; + } + + dev_info(&port->dev, "ACPI _OSC control granted for 0x%02x\n", flags); + + *srv_mask = PCIE_PORT_SERVICE_VC; + if (flags & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL) + *srv_mask |= PCIE_PORT_SERVICE_HP; + if (flags & OSC_PCI_EXPRESS_PME_CONTROL) + *srv_mask |= PCIE_PORT_SERVICE_PME; + if (flags & OSC_PCI_EXPRESS_AER_CONTROL) + *srv_mask |= PCIE_PORT_SERVICE_AER; + + return 0; +} diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index e73effbe402c..a9c222d79ebc 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -14,6 +14,8 @@ #include <linux/string.h> #include <linux/slab.h> #include <linux/pcieport_if.h> +#include <linux/aer.h> +#include <linux/pci-aspm.h> #include "../pci.h" #include "portdrv.h" @@ -236,24 +238,64 @@ static int get_port_device_capability(struct pci_dev *dev) int services = 0, pos; u16 reg16; u32 reg32; + int cap_mask; + int err; + + err = pcie_port_platform_notify(dev, &cap_mask); + if (pcie_ports_auto) { + if (err) { + pcie_no_aspm(); + return 0; + } + } else { + cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP + | PCIE_PORT_SERVICE_VC; + if (pci_aer_available()) + cap_mask |= PCIE_PORT_SERVICE_AER; + } pos = pci_pcie_cap(dev); pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); /* Hot-Plug Capable */ - if (reg16 & PCI_EXP_FLAGS_SLOT) { + if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) { pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, ®32); - if (reg32 & PCI_EXP_SLTCAP_HPC) + if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; + /* + * Disable hot-plug interrupts in case they have been + * enabled by the BIOS and the hot-plug service driver + * is not loaded. + */ + pos += PCI_EXP_SLTCTL; + pci_read_config_word(dev, pos, ®16); + reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); + pci_write_config_word(dev, pos, reg16); + } } /* AER capable */ - if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) + if ((cap_mask & PCIE_PORT_SERVICE_AER) + && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) { services |= PCIE_PORT_SERVICE_AER; + /* + * Disable AER on this port in case it's been enabled by the + * BIOS (the AER service driver will enable it when necessary). + */ + pci_disable_pcie_error_reporting(dev); + } /* VC support */ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) services |= PCIE_PORT_SERVICE_VC; /* Root ports are capable of generating PME too */ - if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) + if ((cap_mask & PCIE_PORT_SERVICE_PME) + && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) { services |= PCIE_PORT_SERVICE_PME; + /* + * Disable PME interrupt on this port in case it's been enabled + * by the BIOS (the PME service driver will enable it when + * necessary). + */ + pcie_pme_interrupt_enable(dev, false); + } return services; } @@ -494,6 +536,9 @@ static void pcie_port_shutdown_service(struct device *dev) {} */ int pcie_port_service_register(struct pcie_port_service_driver *new) { + if (pcie_ports_disabled) + return -ENODEV; + new->driver.name = (char *)new->name; new->driver.bus = &pcie_port_bus_type; new->driver.probe = pcie_port_probe_service; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 3debed25e46b..f9033e190fb6 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -15,6 +15,7 @@ #include <linux/pcieport_if.h> #include <linux/aer.h> #include <linux/dmi.h> +#include <linux/pci-aspm.h> #include "portdrv.h" #include "aer/aerdrv.h" @@ -29,6 +30,31 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +/* If this switch is set, PCIe port native services should not be enabled. */ +bool pcie_ports_disabled; + +/* + * If this switch is set, ACPI _OSC will be used to determine whether or not to + * enable PCIe port native services. + */ +bool pcie_ports_auto = true; + +static int __init pcie_port_setup(char *str) +{ + if (!strncmp(str, "compat", 6)) { + pcie_ports_disabled = true; + } else if (!strncmp(str, "native", 6)) { + pcie_ports_disabled = false; + pcie_ports_auto = false; + } else if (!strncmp(str, "auto", 4)) { + pcie_ports_disabled = false; + pcie_ports_auto = true; + } + + return 1; +} +__setup("pcie_ports=", pcie_port_setup); + /* global data */ static int pcie_portdrv_restore_config(struct pci_dev *dev) @@ -301,6 +327,11 @@ static int __init pcie_portdrv_init(void) { int retval; + if (pcie_ports_disabled) { + pcie_no_aspm(); + return -EACCES; + } + dmi_check_system(pcie_portdrv_dmi_table); retval = pcie_port_bus_register(); @@ -315,11 +346,4 @@ static int __init pcie_portdrv_init(void) return retval; } -static void __exit pcie_portdrv_exit(void) -{ - pci_unregister_driver(&pcie_portdriver); - pcie_port_bus_unregister(); -} - module_init(pcie_portdrv_init); -module_exit(pcie_portdrv_exit); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 89ed181cd90c..857ae01734a6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -163,6 +163,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_d DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs); /* + * Intel NM10 "TigerPoint" LPC PM1a_STS.BM_STS must be clear + * for some HT machines to use C4 w/o hanging. + */ +static void __devinit quirk_tigerpoint_bm_sts(struct pci_dev *dev) +{ + u32 pmbase; + u16 pm1a; + + pci_read_config_dword(dev, 0x40, &pmbase); + pmbase = pmbase & 0xff80; + pm1a = inw(pmbase); + + if (pm1a & 0x10) { + dev_info(&dev->dev, FW_BUG "TigerPoint LPC.BM_STS cleared\n"); + outw(0x10, pmbase); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk_tigerpoint_bm_sts); + +/* * Chipsets where PCI->PCI transfers vanish or hang */ static void __devinit quirk_nopcipci(struct pci_dev *dev) diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 659eaa0fc48f..968cfea04f74 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -49,7 +49,7 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf) } /* these strings match up with the values in pci_bus_speed */ -static char *pci_bus_speed_strings[] = { +static const char *pci_bus_speed_strings[] = { "33 MHz PCI", /* 0x00 */ "66 MHz PCI", /* 0x01 */ "66 MHz PCI-X", /* 0x02 */ diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 54aa1c238cb3..9ba4dade69a4 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -163,7 +163,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev, c = p_dev->function_config; if (!(c->state & CONFIG_LOCKED)) { - dev_dbg(&s->dev, "Configuration isnt't locked\n"); + dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); mutex_unlock(&s->ops_mutex); return -EACCES; } @@ -220,7 +220,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, s->win[w].card_start = offset; ret = s->ops->set_mem_map(s, &s->win[w]); if (ret) - dev_warn(&s->dev, "failed to set_mem_map\n"); + dev_warn(&p_dev->dev, "failed to set_mem_map\n"); mutex_unlock(&s->ops_mutex); return ret; } /* pcmcia_map_mem_page */ @@ -244,18 +244,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, c = p_dev->function_config; if (!(s->state & SOCKET_PRESENT)) { - dev_dbg(&s->dev, "No card present\n"); + dev_dbg(&p_dev->dev, "No card present\n"); ret = -ENODEV; goto unlock; } if (!(c->state & CONFIG_LOCKED)) { - dev_dbg(&s->dev, "Configuration isnt't locked\n"); + dev_dbg(&p_dev->dev, "Configuration isnt't locked\n"); ret = -EACCES; goto unlock; } if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) { - dev_dbg(&s->dev, + dev_dbg(&p_dev->dev, "changing Vcc or IRQ is not allowed at this time\n"); ret = -EINVAL; goto unlock; @@ -265,20 +265,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { if (mod->Vpp1 != mod->Vpp2) { - dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n"); + dev_dbg(&p_dev->dev, + "Vpp1 and Vpp2 must be the same\n"); ret = -EINVAL; goto unlock; } s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) { - dev_printk(KERN_WARNING, &s->dev, + dev_printk(KERN_WARNING, &p_dev->dev, "Unable to set VPP\n"); ret = -EIO; goto unlock; } } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { - dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n"); + dev_dbg(&p_dev->dev, + "changing Vcc is not allowed at this time\n"); ret = -EINVAL; goto unlock; } @@ -401,7 +403,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res) win = &s->win[w]; if (!(p_dev->_win & CLIENT_WIN_REQ(w))) { - dev_dbg(&s->dev, "not releasing unknown window\n"); + dev_dbg(&p_dev->dev, "not releasing unknown window\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -439,7 +441,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, return -ENODEV; if (req->IntType & INT_CARDBUS) { - dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n"); + dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n"); return -EINVAL; } @@ -447,7 +449,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, c = p_dev->function_config; if (c->state & CONFIG_LOCKED) { mutex_unlock(&s->ops_mutex); - dev_dbg(&s->dev, "Configuration is locked\n"); + dev_dbg(&p_dev->dev, "Configuration is locked\n"); return -EACCES; } @@ -455,7 +457,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, s->socket.Vpp = req->Vpp; if (s->ops->set_socket(s, &s->socket)) { mutex_unlock(&s->ops_mutex); - dev_printk(KERN_WARNING, &s->dev, + dev_printk(KERN_WARNING, &p_dev->dev, "Unable to set socket state\n"); return -EINVAL; } @@ -569,19 +571,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) int ret = -EINVAL; mutex_lock(&s->ops_mutex); - dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]); + dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR", + &c->io[0], &c->io[1]); if (!(s->state & SOCKET_PRESENT)) { - dev_dbg(&s->dev, "pcmcia_request_io: No card present\n"); + dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n"); goto out; } if (c->state & CONFIG_LOCKED) { - dev_dbg(&s->dev, "Configuration is locked\n"); + dev_dbg(&p_dev->dev, "Configuration is locked\n"); goto out; } if (c->state & CONFIG_IO_REQ) { - dev_dbg(&s->dev, "IO already configured\n"); + dev_dbg(&p_dev->dev, "IO already configured\n"); goto out; } @@ -592,7 +595,13 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) if (c->io[1].end) { ret = alloc_io_space(s, &c->io[1], p_dev->io_lines); if (ret) { + struct resource tmp = c->io[0]; + /* release the previously allocated resource */ release_io_space(s, &c->io[0]); + /* but preserve the settings, for they worked... */ + c->io[0].end = resource_size(&tmp); + c->io[0].start = tmp.start; + c->io[0].flags = tmp.flags; goto out; } } else @@ -601,7 +610,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev) c->state |= CONFIG_IO_REQ; p_dev->_io = 1; - dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR", + dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR", &c->io[0], &c->io[1]); out: mutex_unlock(&s->ops_mutex); @@ -800,7 +809,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha int w; if (!(s->state & SOCKET_PRESENT)) { - dev_dbg(&s->dev, "No card present\n"); + dev_dbg(&p_dev->dev, "No card present\n"); return -ENODEV; } @@ -809,12 +818,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha req->Size = s->map_size; align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size; if (req->Size & (s->map_size-1)) { - dev_dbg(&s->dev, "invalid map size\n"); + dev_dbg(&p_dev->dev, "invalid map size\n"); return -EINVAL; } if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) || (req->Base & (align-1))) { - dev_dbg(&s->dev, "invalid base address\n"); + dev_dbg(&p_dev->dev, "invalid base address\n"); return -EINVAL; } if (req->Base) @@ -826,7 +835,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha if (!(s->state & SOCKET_WIN_REQ(w))) break; if (w == MAX_WIN) { - dev_dbg(&s->dev, "all windows are used already\n"); + dev_dbg(&p_dev->dev, "all windows are used already\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -837,7 +846,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha win->res = pcmcia_find_mem_region(req->Base, req->Size, align, 0, s); if (!win->res) { - dev_dbg(&s->dev, "allocating mem region failed\n"); + dev_dbg(&p_dev->dev, "allocating mem region failed\n"); mutex_unlock(&s->ops_mutex); return -EINVAL; } @@ -851,7 +860,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha win->card_start = 0; if (s->ops->set_mem_map(s, win) != 0) { - dev_dbg(&s->dev, "failed to set memory mapping\n"); + dev_dbg(&p_dev->dev, "failed to set memory mapping\n"); mutex_unlock(&s->ops_mutex); return -EIO; } @@ -874,7 +883,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha if (win->res) request_resource(&iomem_resource, res); - dev_dbg(&s->dev, "request_window results in %pR\n", res); + dev_dbg(&p_dev->dev, "request_window results in %pR\n", res); mutex_unlock(&s->ops_mutex); *wh = res; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index b8a869af0f44..deef6656ab7b 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -646,7 +646,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev, if (!pci_resource_start(dev, 0)) { dev_warn(&dev->dev, "refusing to load the driver as the " "io_base is NULL.\n"); - goto err_out_free_mem; + goto err_out_disable; } dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx " diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 044f430f3b43..cff7cc2c1f02 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -486,10 +486,12 @@ config TOPSTAR_LAPTOP config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on ACPI + depends on LEDS_CLASS + depends on NEW_LEDS + depends on BACKLIGHT_CLASS_DEVICE depends on INPUT depends on RFKILL || RFKILL = n select INPUT_POLLDEV - select BACKLIGHT_CLASS_DEVICE ---help--- This driver adds support for access to certain system settings on "legacy free" Toshiba laptops. These laptops can be recognized by diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index f15516374987..c1741142a4cb 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -79,12 +79,13 @@ struct bios_args { u32 command; u32 commandtype; u32 datasize; - char *data; + u32 data; }; struct bios_return { u32 sigpass; u32 return_code; + u32 value; }; struct key_entry { @@ -148,7 +149,7 @@ static struct platform_driver hp_wmi_driver = { * buffer = kzalloc(128, GFP_KERNEL); * ret = hp_wmi_perform_query(0x7, 0, buffer, 128) */ -static int hp_wmi_perform_query(int query, int write, char *buffer, +static int hp_wmi_perform_query(int query, int write, u32 *buffer, int buffersize) { struct bios_return bios_return; @@ -159,7 +160,7 @@ static int hp_wmi_perform_query(int query, int write, char *buffer, .command = write ? 0x2 : 0x1, .commandtype = query, .datasize = buffersize, - .data = buffer, + .data = *buffer, }; struct acpi_buffer input = { sizeof(struct bios_args), &args }; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -177,29 +178,14 @@ static int hp_wmi_perform_query(int query, int write, char *buffer, bios_return = *((struct bios_return *)obj->buffer.pointer); - if (bios_return.return_code) { - printk(KERN_WARNING PREFIX "Query %d returned %d\n", query, - bios_return.return_code); - kfree(obj); - return bios_return.return_code; - } - if (obj->buffer.length - sizeof(bios_return) > buffersize) { - kfree(obj); - return -EINVAL; - } - - memset(buffer, 0, buffersize); - memcpy(buffer, - ((char *)obj->buffer.pointer) + sizeof(struct bios_return), - obj->buffer.length - sizeof(bios_return)); - kfree(obj); + memcpy(buffer, &bios_return.value, sizeof(bios_return.value)); return 0; } static int hp_wmi_display_state(void) { - int state; - int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, (char *)&state, + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state, sizeof(state)); if (ret) return -EINVAL; @@ -208,8 +194,8 @@ static int hp_wmi_display_state(void) static int hp_wmi_hddtemp_state(void) { - int state; - int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, (char *)&state, + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state, sizeof(state)); if (ret) return -EINVAL; @@ -218,8 +204,8 @@ static int hp_wmi_hddtemp_state(void) static int hp_wmi_als_state(void) { - int state; - int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, (char *)&state, + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state, sizeof(state)); if (ret) return -EINVAL; @@ -228,8 +214,8 @@ static int hp_wmi_als_state(void) static int hp_wmi_dock_state(void) { - int state; - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state, + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, sizeof(state)); if (ret) @@ -240,8 +226,8 @@ static int hp_wmi_dock_state(void) static int hp_wmi_tablet_state(void) { - int state; - int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, (char *)&state, + int state = 0; + int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, sizeof(state)); if (ret) return ret; @@ -256,7 +242,7 @@ static int hp_wmi_set_block(void *data, bool blocked) int ret; ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, - (char *)&query, sizeof(query)); + &query, sizeof(query)); if (ret) return -EINVAL; return 0; @@ -268,10 +254,10 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = { static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) { - int wireless; + int wireless = 0; int mask; hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, - (char *)&wireless, sizeof(wireless)); + &wireless, sizeof(wireless)); /* TBD: Pass error */ mask = 0x200 << (r * 8); @@ -284,10 +270,10 @@ static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) { - int wireless; + int wireless = 0; int mask; hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, - (char *)&wireless, sizeof(wireless)); + &wireless, sizeof(wireless)); /* TBD: Pass error */ mask = 0x800 << (r * 8); @@ -347,7 +333,7 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u32 tmp = simple_strtoul(buf, NULL, 10); - int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, (char *)&tmp, + int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, sizeof(tmp)); if (ret) return -EINVAL; @@ -421,7 +407,7 @@ static void hp_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; u32 event_id, event_data; - int key_code, ret; + int key_code = 0, ret; u32 *location; acpi_status status; @@ -475,7 +461,7 @@ static void hp_wmi_notify(u32 value, void *context) break; case HPWMI_BEZEL_BUTTON: ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, - (char *)&key_code, + &key_code, sizeof(key_code)); if (ret) break; @@ -578,9 +564,9 @@ static void cleanup_sysfs(struct platform_device *device) static int __devinit hp_wmi_bios_setup(struct platform_device *device) { int err; - int wireless; + int wireless = 0; - err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, (char *)&wireless, + err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless, sizeof(wireless)); if (err) return err; diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 9024480a8228..c44a5e8b8b82 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -51,7 +51,6 @@ * TODO: * - handle CPU hotplug * - provide turbo enable/disable api - * - make sure we can write turbo enable/disable reg based on MISC_EN * * Related documents: * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 @@ -230,7 +229,7 @@ #define THM_TC2 0xac #define THM_DTV 0xb0 #define THM_ITV 0xd8 -#define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */ +#define ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */ #define ITV_ME_SEQNO_SHIFT (16) #define ITV_MCH_TEMP_MASK 0x0000ff00 #define ITV_MCH_TEMP_SHIFT (8) @@ -325,6 +324,7 @@ struct ips_driver { bool gpu_preferred; bool poll_turbo_status; bool second_cpu; + bool turbo_toggle_allowed; struct ips_mcp_limits *limits; /* Optional MCH interfaces for if i915 is in use */ @@ -415,7 +415,7 @@ static void ips_cpu_lower(struct ips_driver *ips) new_limit = cur_limit - 8; /* 1W decrease */ /* Clamp to SKU TDP limit */ - if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK)) + if (new_limit < (ips->orig_turbo_limit & TURBO_TDP_MASK)) new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; thm_writew(THM_MPCPC, (new_limit * 10) / 8); @@ -461,7 +461,8 @@ static void ips_enable_cpu_turbo(struct ips_driver *ips) if (ips->__cpu_turbo_on) return; - on_each_cpu(do_enable_cpu_turbo, ips, 1); + if (ips->turbo_toggle_allowed) + on_each_cpu(do_enable_cpu_turbo, ips, 1); ips->__cpu_turbo_on = true; } @@ -498,7 +499,8 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips) if (!ips->__cpu_turbo_on) return; - on_each_cpu(do_disable_cpu_turbo, ips, 1); + if (ips->turbo_toggle_allowed) + on_each_cpu(do_disable_cpu_turbo, ips, 1); ips->__cpu_turbo_on = false; } @@ -598,17 +600,29 @@ static bool mcp_exceeded(struct ips_driver *ips) { unsigned long flags; bool ret = false; + u32 temp_limit; + u32 avg_power; + const char *msg = "MCP limit exceeded: "; spin_lock_irqsave(&ips->turbo_status_lock, flags); - if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100)) - ret = true; - if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit) + + temp_limit = ips->mcp_temp_limit * 100; + if (ips->mcp_avg_temp > temp_limit) { + dev_info(&ips->dev->dev, + "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp, + temp_limit); ret = true; - spin_unlock_irqrestore(&ips->turbo_status_lock, flags); + } - if (ret) + avg_power = ips->cpu_avg_power + ips->mch_avg_power; + if (avg_power > ips->mcp_power_limit) { dev_info(&ips->dev->dev, - "MCP power or thermal limit exceeded\n"); + "%sAvg power %u, limit %u\n", msg, avg_power, + ips->mcp_power_limit); + ret = true; + } + + spin_unlock_irqrestore(&ips->turbo_status_lock, flags); return ret; } @@ -663,6 +677,27 @@ static bool mch_exceeded(struct ips_driver *ips) } /** + * verify_limits - verify BIOS provided limits + * @ips: IPS structure + * + * BIOS can optionally provide non-default limits for power and temp. Check + * them here and use the defaults if the BIOS values are not provided or + * are otherwise unusable. + */ +static void verify_limits(struct ips_driver *ips) +{ + if (ips->mcp_power_limit < ips->limits->mcp_power_limit || + ips->mcp_power_limit > 35000) + ips->mcp_power_limit = ips->limits->mcp_power_limit; + + if (ips->mcp_temp_limit < ips->limits->core_temp_limit || + ips->mcp_temp_limit < ips->limits->mch_temp_limit || + ips->mcp_temp_limit > 150) + ips->mcp_temp_limit = min(ips->limits->core_temp_limit, + ips->limits->mch_temp_limit); +} + +/** * update_turbo_limits - get various limits & settings from regs * @ips: IPS driver struct * @@ -680,12 +715,21 @@ static void update_turbo_limits(struct ips_driver *ips) u32 hts = thm_readl(THM_HTS); ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); - ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); + /* + * Disable turbo for now, until we can figure out why the power figures + * are wrong + */ + ips->cpu_turbo_enabled = false; + + if (ips->gpu_busy) + ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); + ips->core_power_limit = thm_readw(THM_MPCPC); ips->mch_power_limit = thm_readw(THM_MMGPC); ips->mcp_temp_limit = thm_readw(THM_PTL); ips->mcp_power_limit = thm_readw(THM_MPPC); + verify_limits(ips); /* Ignore BIOS CPU vs GPU pref */ } @@ -858,7 +902,7 @@ static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period) ret = (ret * 1000) / 65535; *last = val; - return ret; + return 0; } static const u16 temp_decay_factor = 2; @@ -940,7 +984,6 @@ static int ips_monitor(void *data) kfree(mch_samples); kfree(cpu_samples); kfree(mchp_samples); - kthread_stop(ips->adjust); return -ENOMEM; } @@ -948,7 +991,7 @@ static int ips_monitor(void *data) ITV_ME_SEQNO_SHIFT; seqno_timestamp = get_jiffies_64(); - old_cpu_power = thm_readl(THM_CEC) / 65535; + old_cpu_power = thm_readl(THM_CEC); schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); /* Collect an initial average */ @@ -1150,11 +1193,18 @@ static irqreturn_t ips_irq_handler(int irq, void *arg) STS_GPL_SHIFT; /* ignore EC CPU vs GPU pref */ ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); - ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); + /* + * Disable turbo for now, until we can figure + * out why the power figures are wrong + */ + ips->cpu_turbo_enabled = false; + if (ips->gpu_busy) + ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> STS_PTL_SHIFT; ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> STS_PPL_SHIFT; + verify_limits(ips); spin_unlock(&ips->turbo_status_lock); thm_writeb(THM_SEC, SEC_ACK); @@ -1333,8 +1383,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) * turbo manually or we'll get an illegal MSR access, even though * turbo will still be available. */ - if (!(misc_en & IA32_MISC_TURBO_EN)) - ; /* add turbo MSR write allowed flag if necessary */ + if (misc_en & IA32_MISC_TURBO_EN) + ips->turbo_toggle_allowed = true; + else + ips->turbo_toggle_allowed = false; if (strstr(boot_cpu_data.x86_model_id, "CPU M")) limits = &ips_sv_limits; @@ -1351,9 +1403,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) tdp = turbo_power & TURBO_TDP_MASK; /* Sanity check TDP against CPU */ - if (limits->mcp_power_limit != (tdp / 8) * 1000) { - dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n", - tdp / 8, limits->mcp_power_limit / 1000); + if (limits->core_power_limit != (tdp / 8) * 1000) { + dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n", + tdp / 8, limits->core_power_limit / 1000); + limits->core_power_limit = (tdp / 8) * 1000; } out: @@ -1390,7 +1443,7 @@ static bool ips_get_i915_syms(struct ips_driver *ips) return true; out_put_busy: - symbol_put(i915_gpu_turbo_disable); + symbol_put(i915_gpu_busy); out_put_lower: symbol_put(i915_gpu_lower); out_put_raise: @@ -1532,22 +1585,27 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) /* Save turbo limits & ratios */ rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); - ips_enable_cpu_turbo(ips); - ips->cpu_turbo_enabled = true; + ips_disable_cpu_turbo(ips); + ips->cpu_turbo_enabled = false; - /* Set up the work queue and monitor/adjust threads */ - ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); - if (IS_ERR(ips->monitor)) { + /* Create thermal adjust thread */ + ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); + if (IS_ERR(ips->adjust)) { dev_err(&dev->dev, - "failed to create thermal monitor thread, aborting\n"); + "failed to create thermal adjust thread, aborting\n"); ret = -ENOMEM; goto error_free_irq; + } - ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); - if (IS_ERR(ips->adjust)) { + /* + * Set up the work queue and monitor thread. The monitor thread + * will wake up ips_adjust thread. + */ + ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); + if (IS_ERR(ips->monitor)) { dev_err(&dev->dev, - "failed to create thermal adjust thread, aborting\n"); + "failed to create thermal monitor thread, aborting\n"); ret = -ENOMEM; goto error_thread_cleanup; } @@ -1566,7 +1624,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) return ret; error_thread_cleanup: - kthread_stop(ips->monitor); + kthread_stop(ips->adjust); error_free_irq: free_irq(ips->dev->irq, ips); error_unmap: diff --git a/drivers/platform/x86/intel_rar_register.c b/drivers/platform/x86/intel_rar_register.c index 73f8e6d72669..2b11a33325e6 100644 --- a/drivers/platform/x86/intel_rar_register.c +++ b/drivers/platform/x86/intel_rar_register.c @@ -145,7 +145,7 @@ static void free_rar_device(struct rar_device *rar) */ static struct rar_device *_rar_to_device(int rar, int *off) { - if (rar >= 0 && rar <= 3) { + if (rar >= 0 && rar < MRST_NUM_RAR) { *off = rar; return &my_rar_device; } diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index 943f9084dcb1..6abe18e638e9 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -487,7 +487,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data) mdelay(1); *data = readl(ipcdev.i2c_base + I2C_DATA_ADDR); } else if (cmd == IPC_I2C_WRITE) { - writel(addr, ipcdev.i2c_base + I2C_DATA_ADDR); + writel(*data, ipcdev.i2c_base + I2C_DATA_ADDR); mdelay(1); writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR); } else { diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e35ed128bdef..2d61186ad5a2 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3093,7 +3093,8 @@ static const struct tpacpi_quirk tpacpi_hotkey_qtable[] __initconst = { TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */ }; -typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; +typedef u16 tpacpi_keymap_entry_t; +typedef tpacpi_keymap_entry_t tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; static int __init hotkey_init(struct ibm_init_struct *iibm) { @@ -3230,7 +3231,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) }; #define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t) -#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0]) +#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_entry_t) int res, i; int status; diff --git a/drivers/power/apm_power.c b/drivers/power/apm_power.c index 936bae560fa1..dc628cb2e762 100644 --- a/drivers/power/apm_power.c +++ b/drivers/power/apm_power.c @@ -233,6 +233,7 @@ static int calculate_capacity(enum apm_source source) empty_design_prop = POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN; now_prop = POWER_SUPPLY_PROP_ENERGY_NOW; avg_prop = POWER_SUPPLY_PROP_ENERGY_AVG; + break; case SOURCE_VOLTAGE: full_prop = POWER_SUPPLY_PROP_VOLTAGE_MAX; empty_prop = POWER_SUPPLY_PROP_VOLTAGE_MIN; diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c index c61ffec2ff10..2a10cd361181 100644 --- a/drivers/power/intel_mid_battery.c +++ b/drivers/power/intel_mid_battery.c @@ -185,8 +185,8 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) { u32 data[3]; u8 *p = (u8 *)&data[1]; - int err = intel_scu_ipc_command(IPC_CMD_BATTERY_PROPERTY, - IPCMSG_BATTERY, NULL, 0, data, 3); + int err = intel_scu_ipc_command(IPCMSG_BATTERY, + IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3); prop->capacity = data[0]; prop->crnt = *p++; @@ -207,7 +207,7 @@ static int pmic_scu_ipc_battery_property_get(struct battery_property *prop) static int pmic_scu_ipc_set_charger(int charger) { - return intel_scu_ipc_simple_command(charger, IPCMSG_BATTERY); + return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger); } /** diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 7d149a8d8d9b..2ce2eb71d0f5 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -215,7 +215,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); int ret = -EINVAL; - if (info->vol_table && (index < (2 << info->vol_nbits))) { + if (info->vol_table && (index < (1 << info->vol_nbits))) { ret = info->vol_table[index]; if (info->slope_double) ret <<= 1; @@ -233,7 +233,7 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) max_uV = max_uV >> 1; } if (info->vol_table) { - for (i = 0; i < (2 << info->vol_nbits); i++) { + for (i = 0; i < (1 << info->vol_nbits); i++) { if (!info->vol_table[i]) break; if ((min_uV <= info->vol_table[i]) diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 11790990277a..b349266a43de 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -634,12 +634,9 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) "%s: failed to register regulator %s err %d\n", __func__, ab3100_regulator_desc[i].name, err); - i--; /* remove the already registered regulators */ - while (i > 0) { + while (--i >= 0) regulator_unregister(ab3100_regulators[i].rdev); - i--; - } return err; } diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index dc3f1a491675..28c7ae67cec9 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -157,7 +157,7 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector) if (info->fixed_uV) return info->fixed_uV; - if (selector > info->voltages_len) + if (selector >= info->voltages_len) return -EINVAL; return info->supported_voltages[selector]; @@ -344,13 +344,14 @@ static inline struct ab8500_regulator_info *find_regulator_info(int id) static __devinit int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); - struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev); + struct ab8500_platform_data *pdata; int i, err; if (!ab8500) { dev_err(&pdev->dev, "null mfd parent\n"); return -EINVAL; } + pdata = dev_get_platdata(ab8500->dev); /* register all regulators */ for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { @@ -368,11 +369,9 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); /* when we fail, un-register all earlier regulators */ - i--; - while (i > 0) { + while (--i >= 0) { info = &ab8500_regulator_info[i]; regulator_unregister(info->regulator); - i--; } return err; } diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index d59d2f2314af..a4be41614eeb 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -25,7 +25,7 @@ struct ad5398_chip_info { unsigned int current_level; unsigned int current_mask; unsigned int current_offset; - struct regulator_dev rdev; + struct regulator_dev *rdev; }; static int ad5398_calc_current(struct ad5398_chip_info *chip, @@ -211,7 +211,6 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id); static int __devinit ad5398_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct regulator_dev *rdev; struct regulator_init_data *init_data = client->dev.platform_data; struct ad5398_chip_info *chip; const struct ad5398_current_data_format *df = @@ -233,9 +232,10 @@ static int __devinit ad5398_probe(struct i2c_client *client, chip->current_offset = df->current_offset; chip->current_mask = (chip->current_level - 1) << chip->current_offset; - rdev = regulator_register(&ad5398_reg, &client->dev, init_data, chip); - if (IS_ERR(rdev)) { - ret = PTR_ERR(rdev); + chip->rdev = regulator_register(&ad5398_reg, &client->dev, + init_data, chip); + if (IS_ERR(chip->rdev)) { + ret = PTR_ERR(chip->rdev); dev_err(&client->dev, "failed to register %s %s\n", id->name, ad5398_reg.name); goto err; @@ -254,9 +254,8 @@ static int __devexit ad5398_remove(struct i2c_client *client) { struct ad5398_chip_info *chip = i2c_get_clientdata(client); - regulator_unregister(&chip->rdev); + regulator_unregister(chip->rdev); kfree(chip); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 422a709d271d..cc8b337b9119 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -700,7 +700,7 @@ static void print_constraints(struct regulator_dev *rdev) constraints->min_uA != constraints->max_uA) { ret = _regulator_get_current_limit(rdev); if (ret > 0) - count += sprintf(buf + count, "at %d uA ", ret / 1000); + count += sprintf(buf + count, "at %d mA ", ret / 1000); } if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) @@ -2302,8 +2302,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); ret = device_register(&rdev->dev); - if (ret != 0) + if (ret != 0) { + put_device(&rdev->dev); goto clean; + } dev_set_drvdata(&rdev->dev, rdev); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e49d2bd393f2..b8cc6389a541 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -165,7 +165,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, mutex_init(&pmic->mtx); for (i = 0; i < 3; i++) { - pmic->rdev[i] = regulator_register(&isl_rd[0], &i2c->dev, + pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, init_data, pmic); if (IS_ERR(pmic->rdev[i])) { dev_err(&i2c->dev, "failed to register %s\n", id->name); @@ -191,8 +191,6 @@ static int __devexit isl6271a_remove(struct i2c_client *i2c) struct isl_pmic *pmic = i2c_get_clientdata(i2c); int i; - i2c_set_clientdata(i2c, NULL); - for (i = 0; i < 3; i++) regulator_unregister(pmic->rdev[i]); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 8867c2710a6d..559cfa271a44 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -121,14 +121,14 @@ static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) return -EINVAL; - if (min_uV >= 3000000) - selector = 3; - if (min_uV < 3000000) - selector = 2; - if (min_uV < 2500000) - selector = 1; if (min_uV < 1800000) selector = 0; + else if (min_uV < 2500000) + selector = 1; + else if (min_uV < 3000000) + selector = 2; + else if (min_uV >= 3000000) + selector = 3; if (max1586_v6_calc_voltage(selector) > max_uV) return -EINVAL; diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 4520ace3f7e7..6b60a9c0366b 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -330,7 +330,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, /* set external clock frequency */ info->extclk_freq = pdata->extclk_freq; max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK, - info->extclk_freq); + info->extclk_freq << 6); } if (pdata->ramp_timing) { diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index ab67298799f9..a1baf1fbe004 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -549,7 +549,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) if (!max8998) return -ENOMEM; - size = sizeof(struct regulator_dev *) * (pdata->num_regulators + 1); + size = sizeof(struct regulator_dev *) * pdata->num_regulators; max8998->rdev = kzalloc(size, GFP_KERNEL); if (!max8998->rdev) { kfree(max8998); @@ -557,7 +557,9 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) } rdev = max8998->rdev; + max8998->dev = &pdev->dev; max8998->iodev = iodev; + max8998->num_regulators = pdata->num_regulators; platform_set_drvdata(pdev, max8998); for (i = 0; i < pdata->num_regulators; i++) { @@ -583,7 +585,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) return 0; err: - for (i = 0; i <= max8998->num_regulators; i++) + for (i = 0; i < max8998->num_regulators; i++) if (rdev[i]) regulator_unregister(rdev[i]); @@ -599,7 +601,7 @@ static int __devexit max8998_pmic_remove(struct platform_device *pdev) struct regulator_dev **rdev = max8998->rdev; int i; - for (i = 0; i <= max8998->num_regulators; i++) + for (i = 0; i < max8998->num_regulators; i++) if (rdev[i]) regulator_unregister(rdev[i]); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index c239f42aa4a3..020f5878d7ff 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -626,12 +626,6 @@ fail: return error; } -/** - * tps6507x_remove - TPS6507x driver i2c remove handler - * @client: i2c driver client device structure - * - * Unregister TPS driver as an i2c client device driver - */ static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 8cff1413a147..51237fbb1bbb 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -133,7 +133,7 @@ static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; val = (val & mask) >> ri->volt_shift; - if (val > ri->desc.n_voltages) + if (val >= ri->desc.n_voltages) BUG(); return ri->voltages[val] * 1000; @@ -150,7 +150,7 @@ static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, if (ret) return ret; - return tps6586x_set_bits(parent, ri->go_reg, ri->go_bit); + return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); } static int tps6586x_regulator_enable(struct regulator_dev *rdev) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index e686cdb61b97..9edf8f692341 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -215,8 +215,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, case REGULATOR_MODE_IDLE: ret = wm831x_set_bits(wm831x, ctrl_reg, - WM831X_LDO1_LP_MODE, - WM831X_LDO1_LP_MODE); + WM831X_LDO1_LP_MODE, 0); if (ret < 0) return ret; @@ -225,10 +224,12 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev, WM831X_LDO1_ON_MODE); if (ret < 0) return ret; + break; case REGULATOR_MODE_STANDBY: ret = wm831x_set_bits(wm831x, ctrl_reg, - WM831X_LDO1_LP_MODE, 0); + WM831X_LDO1_LP_MODE, + WM831X_LDO1_LP_MODE); if (ret < 0) return ret; diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 0e6ed7db9364..fe4b8a8a9dfd 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1129,7 +1129,7 @@ static unsigned int wm8350_dcdc_get_mode(struct regulator_dev *rdev) mode = REGULATOR_MODE_NORMAL; } else if (!active && !sleep) mode = REGULATOR_MODE_IDLE; - else if (!sleep) + else if (sleep) mode = REGULATOR_MODE_STANDBY; return mode; diff --git a/drivers/rtc/rtc-ab3100.c b/drivers/rtc/rtc-ab3100.c index d26780ea254b..261a07e0fb24 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c @@ -235,6 +235,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) err = PTR_ERR(rtc); return err; } + platform_set_drvdata(pdev, rtc); return 0; } @@ -244,6 +245,7 @@ static int __exit ab3100_rtc_remove(struct platform_device *pdev) struct rtc_device *rtc = platform_get_drvdata(pdev); rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 72b2bcc2c224..d4fb82d85e9b 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -426,7 +426,7 @@ static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) enable_irq_wake(IRQ_RTC); bfin_rtc_sync_pending(&pdev->dev); } else - bfin_rtc_int_clear(-1); + bfin_rtc_int_clear(0); return 0; } @@ -435,8 +435,17 @@ static int bfin_rtc_resume(struct platform_device *pdev) { if (device_may_wakeup(&pdev->dev)) disable_irq_wake(IRQ_RTC); - else - bfin_write_RTC_ISTAT(-1); + + /* + * Since only some of the RTC bits are maintained externally in the + * Vbat domain, we need to wait for the RTC MMRs to be synced into + * the core after waking up. This happens every RTC 1HZ. Once that + * has happened, we can go ahead and re-enable the important write + * complete interrupt event. + */ + while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_SEC)) + continue; + bfin_rtc_int_set(RTC_ISTAT_WRITE_COMPLETE); return 0; } diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c index 9daed8db83d3..9de8516e3531 100644 --- a/drivers/rtc/rtc-ds3232.c +++ b/drivers/rtc/rtc-ds3232.c @@ -268,7 +268,6 @@ out_irq: free_irq(client->irq, client); out_free: - i2c_set_clientdata(client, NULL); kfree(ds3232); return ret; } @@ -287,7 +286,6 @@ static int __devexit ds3232_remove(struct i2c_client *client) } rtc_device_unregister(ds3232->rtc); - i2c_set_clientdata(client, NULL); kfree(ds3232); return 0; } diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 66377f3e28b8..d60557cae8ef 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -364,7 +364,7 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) t->time.tm_isdst = -1; t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE); t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF); - return rtc_valid_tm(t); + return 0; } static struct rtc_class_ops m41t80_rtc_ops = { diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 6c418fe7f288..b7a6690e5b35 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -403,7 +403,7 @@ static int pl031_probe(struct amba_device *adev, struct amba_id *id) } if (request_irq(adev->irq[0], pl031_interrupt, - IRQF_DISABLED | IRQF_SHARED, "rtc-pl031", ldata)) { + IRQF_DISABLED, "rtc-pl031", ldata)) { ret = -EIO; goto out_no_irq; } diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a0d3ec89d412..f57a87f4ae96 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -310,11 +310,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) s3c_rtc_setaie(alrm->enabled); - if (alrm->enabled) - enable_irq_wake(s3c_rtc_alarmno); - else - disable_irq_wake(s3c_rtc_alarmno); - return 0; } @@ -587,6 +582,10 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) ticnt_en_save &= S3C64XX_RTCCON_TICEN; } s3c_rtc_enable(pdev, 0); + + if (device_may_wakeup(&pdev->dev)) + enable_irq_wake(s3c_rtc_alarmno); + return 0; } @@ -600,6 +599,10 @@ static int s3c_rtc_resume(struct platform_device *pdev) tmp = readb(s3c_rtc_base + S3C2410_RTCCON); writeb(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON); } + + if (device_may_wakeup(&pdev->dev)) + disable_irq_wake(s3c_rtc_alarmno); + return 0; } #else diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c index c6cbcb3f925e..0e9a309b9669 100644 --- a/drivers/s390/char/ctrlchar.c +++ b/drivers/s390/char/ctrlchar.c @@ -16,12 +16,11 @@ #ifdef CONFIG_MAGIC_SYSRQ static int ctrlchar_sysrq_key; -static struct tty_struct *sysrq_tty; static void ctrlchar_handle_sysrq(struct work_struct *work) { - handle_sysrq(ctrlchar_sysrq_key, sysrq_tty); + handle_sysrq(ctrlchar_sysrq_key); } static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq); @@ -54,7 +53,6 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty) /* racy */ if (len == 3 && buf[1] == '-') { ctrlchar_sysrq_key = buf[2]; - sysrq_tty = tty; schedule_work(&ctrlchar_work); return CTRLCHAR_SYSRQ; } diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 18d9a497863b..8cd58e412b5e 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -305,7 +305,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode) if (kbd->sysrq) { if (kbd->sysrq == K(KT_LATIN, '-')) { kbd->sysrq = 0; - handle_sysrq(value, kbd->tty); + handle_sysrq(value); return; } if (value == '-') { diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index b7de02525ec9..85cf607fc78f 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -217,8 +217,7 @@ tapeblock_setup_device(struct tape_device * device) if (!blkdat->request_queue) return -ENOMEM; - elevator_exit(blkdat->request_queue->elevator); - rc = elevator_init(blkdat->request_queue, "noop"); + rc = elevator_change(blkdat->request_queue, "noop"); if (rc) goto cleanup_queue; diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 6edf20b62de5..2c7d2d9be4d0 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -1154,7 +1154,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) dev_fsm, dev_fsm_len, GFP_KERNEL); if (priv->fsm == NULL) { CTCMY_DBF_DEV(SETUP, dev, "init_fsm error"); - kfree(dev); + free_netdev(dev); return NULL; } fsm_newstate(priv->fsm, DEV_STATE_STOPPED); @@ -1165,7 +1165,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) grp = ctcmpc_init_mpc_group(priv); if (grp == NULL) { MPC_DBF_DEV(SETUP, dev, "init_mpc_group error"); - kfree(dev); + free_netdev(dev); return NULL; } tasklet_init(&grp->mpc_tasklet2, diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 7d4d2275573c..7f11f3e48e12 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -300,8 +300,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf) { struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); - int len = 0; - int status; + int status = 0; SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); switch (param) { @@ -315,7 +314,7 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, default: return iscsi_host_get_param(shost, param, buf); } - return len; + return status; } int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 26350e470bcc..877324fc594c 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -368,7 +368,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, memset(req, 0, sizeof(*req)); wrb->tag0 |= tag; - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 1); + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, sizeof(*req)); diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index cd05e049d5f6..d0c82340f0e2 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1404,13 +1404,13 @@ void scsi_print_sense(char *name, struct scsi_cmnd *cmd) { struct scsi_sense_hdr sshdr; - scmd_printk(KERN_INFO, cmd, ""); + scmd_printk(KERN_INFO, cmd, " "); scsi_decode_sense_buffer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sshdr); scsi_show_sense_hdr(&sshdr); scsi_decode_sense_extras(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE, &sshdr); - scmd_printk(KERN_INFO, cmd, ""); + scmd_printk(KERN_INFO, cmd, " "); scsi_show_extd_sense(sshdr.asc, sshdr.ascq); } EXPORT_SYMBOL(scsi_print_sense); @@ -1453,7 +1453,7 @@ EXPORT_SYMBOL(scsi_show_result); void scsi_print_result(struct scsi_cmnd *cmd) { - scmd_printk(KERN_INFO, cmd, ""); + scmd_printk(KERN_INFO, cmd, " "); scsi_show_result(cmd->result); } EXPORT_SYMBOL(scsi_print_result); diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4f5551b5fe53..c5d0606ad097 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3231,6 +3231,12 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) misc_fw_support = readl(&cfgtable->misc_fw_support); use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET; + /* The doorbell reset seems to cause lockups on some Smart + * Arrays (e.g. P410, P410i, maybe others). Until this is + * fixed or at least isolated, avoid the doorbell reset. + */ + use_doorbell = 0; + rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell); if (rc) goto unmap_cfgtable; diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index fda4de3440c4..e88bbdde49c5 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -865,7 +865,7 @@ void osd_req_read(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); WARN_ON(or->in.bio || or->in.total_bytes); - WARN_ON(1 == (bio->bi_rw & REQ_WRITE)); + WARN_ON(bio->bi_rw & REQ_WRITE); or->in.bio = bio; or->in.total_bytes = len; } diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 420238cc794e..114bc5a81171 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -1838,26 +1838,33 @@ qla24xx_vport_delete(struct fc_vport *fc_vport) qla24xx_disable_vp(vha); + vha->flags.delete_progress = 1; + fc_remove_host(vha->host); scsi_remove_host(vha->host); - qla2x00_free_fcports(vha); + if (vha->timer_active) { + qla2x00_vp_stop_timer(vha); + DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]" + " = %p has stopped\n", vha->host_no, vha->vp_idx, vha)); + } qla24xx_deallocate_vp_id(vha); + /* No pending activities shall be there on the vha now */ + DEBUG(msleep(random32()%10)); /* Just to see if something falls on + * the net we have placed below */ + + BUG_ON(atomic_read(&vha->vref_count)); + + qla2x00_free_fcports(vha); + mutex_lock(&ha->vport_lock); ha->cur_vport_count--; clear_bit(vha->vp_idx, ha->vp_idx_map); mutex_unlock(&ha->vport_lock); - if (vha->timer_active) { - qla2x00_vp_stop_timer(vha); - DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p " - "has stopped\n", - vha->host_no, vha->vp_idx, vha)); - } - if (vha->req->id && !ha->flags.cpu_affinity_enabled) { if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS) qla_printk(KERN_WARNING, ha, diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 6cfc28a25eb3..b74e6b5743dc 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -29,8 +29,6 @@ /* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ /* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */ -/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */ - /* * Macros use for debugging the driver. */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3a432ea0c7a3..d2a4e1530708 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2641,6 +2641,7 @@ struct qla_hw_data { #define MBX_UPDATE_FLASH_ACTIVE 3 struct mutex vport_lock; /* Virtual port synchronization */ + spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */ struct completion mbx_cmd_comp; /* Serialize mbx access */ struct completion mbx_intr_comp; /* Used for completion notification */ struct completion dcbx_comp; /* For set port config notification */ @@ -2828,6 +2829,7 @@ typedef struct scsi_qla_host { uint32_t management_server_logged_in :1; uint32_t process_response_queue :1; uint32_t difdix_supported:1; + uint32_t delete_progress:1; } flags; atomic_t loop_state; @@ -2922,6 +2924,8 @@ typedef struct scsi_qla_host { struct req_que *req; int fw_heartbeat_counter; int seconds_since_last_heartbeat; + + atomic_t vref_count; } scsi_qla_host_t; /* @@ -2932,6 +2936,22 @@ typedef struct scsi_qla_host { test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ atomic_read(&ha->loop_state) == LOOP_DOWN) +#define QLA_VHA_MARK_BUSY(__vha, __bail) do { \ + atomic_inc(&__vha->vref_count); \ + mb(); \ + if (__vha->flags.delete_progress) { \ + atomic_dec(&__vha->vref_count); \ + __bail = 1; \ + } else { \ + __bail = 0; \ + } \ +} while (0) + +#define QLA_VHA_MARK_NOT_BUSY(__vha) do { \ + atomic_dec(&__vha->vref_count); \ +} while (0) + + #define qla_printk(level, ha, format, arg...) \ dev_printk(level , &((ha)->pdev->dev) , format , ## arg) diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d863ed2619b5..9c383baebe27 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -69,21 +69,29 @@ qla2x00_ctx_sp_free(srb_t *sp) { struct srb_ctx *ctx = sp->ctx; struct srb_iocb *iocb = ctx->u.iocb_cmd; + struct scsi_qla_host *vha = sp->fcport->vha; del_timer_sync(&iocb->timer); kfree(iocb); kfree(ctx); mempool_free(sp, sp->fcport->vha->hw->srb_mempool); + + QLA_VHA_MARK_NOT_BUSY(vha); } inline srb_t * qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, unsigned long tmo) { - srb_t *sp; + srb_t *sp = NULL; struct qla_hw_data *ha = vha->hw; struct srb_ctx *ctx; struct srb_iocb *iocb; + uint8_t bail; + + QLA_VHA_MARK_BUSY(vha, bail); + if (bail) + return NULL; sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL); if (!sp) @@ -116,6 +124,8 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size, iocb->timer.function = qla2x00_ctx_sp_timeout; add_timer(&iocb->timer); done: + if (!sp) + QLA_VHA_MARK_NOT_BUSY(vha); return sp; } @@ -1777,11 +1787,15 @@ qla2x00_init_rings(scsi_qla_host_t *vha) qla2x00_init_response_q_entries(rsp); } + spin_lock_irqsave(&ha->vport_slock, flags); /* Clear RSCN queue. */ list_for_each_entry(vp, &ha->vp_list, list) { vp->rscn_in_ptr = 0; vp->rscn_out_ptr = 0; } + + spin_unlock_irqrestore(&ha->vport_slock, flags); + ha->isp_ops->config_rings(vha); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -3218,12 +3232,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, /* Bypass virtual ports of the same host. */ found = 0; if (ha->num_vhosts) { + unsigned long flags; + + spin_lock_irqsave(&ha->vport_slock, flags); list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (new_fcport->d_id.b24 == vp->d_id.b24) { found = 1; break; } } + spin_unlock_irqrestore(&ha->vport_slock, flags); + if (found) continue; } @@ -3343,6 +3362,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; struct scsi_qla_host *tvp; + unsigned long flags = 0; rval = QLA_SUCCESS; @@ -3367,6 +3387,8 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) /* Check for loop ID being already in use. */ found = 0; fcport = NULL; + + spin_lock_irqsave(&ha->vport_slock, flags); list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { list_for_each_entry(fcport, &vp->vp_fcports, list) { if (fcport->loop_id == dev->loop_id && @@ -3379,6 +3401,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) if (found) break; } + spin_unlock_irqrestore(&ha->vport_slock, flags); /* If not in use then it is free to use. */ if (!found) { @@ -3791,14 +3814,27 @@ void qla2x00_update_fcports(scsi_qla_host_t *base_vha) { fc_port_t *fcport; - struct scsi_qla_host *tvp, *vha; + struct scsi_qla_host *vha; + struct qla_hw_data *ha = base_vha->hw; + unsigned long flags; + spin_lock_irqsave(&ha->vport_slock, flags); /* Go with deferred removal of rport references. */ - list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list) - list_for_each_entry(fcport, &vha->vp_fcports, list) + list_for_each_entry(vha, &base_vha->hw->vp_list, list) { + atomic_inc(&vha->vref_count); + list_for_each_entry(fcport, &vha->vp_fcports, list) { if (fcport && fcport->drport && - atomic_read(&fcport->state) != FCS_UNCONFIGURED) + atomic_read(&fcport->state) != FCS_UNCONFIGURED) { + spin_unlock_irqrestore(&ha->vport_slock, flags); + qla2x00_rport_del(fcport); + + spin_lock_irqsave(&ha->vport_slock, flags); + } + } + atomic_dec(&vha->vref_count); + } + spin_unlock_irqrestore(&ha->vport_slock, flags); } void @@ -3806,7 +3842,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); - struct scsi_qla_host *tvp; + unsigned long flags; vha->flags.online = 0; ha->flags.chip_reset_done = 0; @@ -3824,8 +3860,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(vha, 0); - list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list) + + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vp, &base_vha->hw->vp_list, list) { + atomic_inc(&vp->vref_count); + spin_unlock_irqrestore(&ha->vport_slock, flags); + qla2x00_mark_all_devices_lost(vp, 0); + + spin_lock_irqsave(&ha->vport_slock, flags); + atomic_dec(&vp->vref_count); + } + spin_unlock_irqrestore(&ha->vport_slock, flags); } else { if (!atomic_read(&vha->loop_down_timer)) atomic_set(&vha->loop_down_timer, @@ -3862,8 +3908,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) uint8_t status = 0; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; - struct scsi_qla_host *tvp; struct req_que *req = ha->req_q_map[0]; + unsigned long flags; if (vha->flags.online) { qla2x00_abort_isp_cleanup(vha); @@ -3970,10 +4016,21 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) DEBUG(printk(KERN_INFO "qla2x00_abort_isp(%ld): succeeded.\n", vha->host_no)); - list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { - if (vp->vp_idx) + + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vp, &ha->vp_list, list) { + if (vp->vp_idx) { + atomic_inc(&vp->vref_count); + spin_unlock_irqrestore(&ha->vport_slock, flags); + qla2x00_vp_abort_isp(vp); + + spin_lock_irqsave(&ha->vport_slock, flags); + atomic_dec(&vp->vref_count); + } } + spin_unlock_irqrestore(&ha->vport_slock, flags); + } else { qla_printk(KERN_INFO, ha, "qla2x00_abort_isp: **** FAILED ****\n"); @@ -5185,7 +5242,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) struct req_que *req = ha->req_q_map[0]; struct rsp_que *rsp = ha->rsp_q_map[0]; struct scsi_qla_host *vp; - struct scsi_qla_host *tvp; + unsigned long flags; status = qla2x00_init_rings(vha); if (!status) { @@ -5272,10 +5329,21 @@ qla82xx_restart_isp(scsi_qla_host_t *vha) DEBUG(printk(KERN_INFO "qla82xx_restart_isp(%ld): succeeded.\n", vha->host_no)); - list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { - if (vp->vp_idx) + + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vp, &ha->vp_list, list) { + if (vp->vp_idx) { + atomic_inc(&vp->vref_count); + spin_unlock_irqrestore(&ha->vport_slock, flags); + qla2x00_vp_abort_isp(vp); + + spin_lock_irqsave(&ha->vport_slock, flags); + atomic_dec(&vp->vref_count); + } } + spin_unlock_irqrestore(&ha->vport_slock, flags); + } else { qla_printk(KERN_INFO, ha, "qla82xx_restart_isp: **** FAILED ****\n"); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6982ba70e12a..28f65be19dad 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1706,19 +1706,20 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) cp->result = DID_ERROR << 16; break; } - } else if (!lscsi_status) { + } else { DEBUG2(qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d) Dropped frame(s) detected (0x%x " "of 0x%x bytes).\n", vha->host_no, cp->device->id, cp->device->lun, resid, scsi_bufflen(cp))); - cp->result = DID_ERROR << 16; - break; + cp->result = DID_ERROR << 16 | lscsi_status; + goto check_scsi_status; } cp->result = DID_OK << 16 | lscsi_status; logit = 0; +check_scsi_status: /* * Check to see if SCSI Status is non zero. If so report SCSI * Status. diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 6009b0c69488..a595ec8264f8 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2913,7 +2913,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; - scsi_qla_host_t *tvp; + unsigned long flags; if (rptid_entry->entry_status != 0) return; @@ -2945,9 +2945,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, return; } - list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vp, &ha->vp_list, list) if (vp_idx == vp->vp_idx) break; + spin_unlock_irqrestore(&ha->vport_slock, flags); + if (!vp) return; diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 987c5b0ca78e..2b69392a71a1 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -30,6 +30,7 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) { uint32_t vp_id; struct qla_hw_data *ha = vha->hw; + unsigned long flags; /* Find an empty slot and assign an vp_id */ mutex_lock(&ha->vport_lock); @@ -44,7 +45,11 @@ qla24xx_allocate_vp_id(scsi_qla_host_t *vha) set_bit(vp_id, ha->vp_idx_map); ha->num_vhosts++; vha->vp_idx = vp_id; + + spin_lock_irqsave(&ha->vport_slock, flags); list_add_tail(&vha->list, &ha->vp_list); + spin_unlock_irqrestore(&ha->vport_slock, flags); + mutex_unlock(&ha->vport_lock); return vp_id; } @@ -54,12 +59,31 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha) { uint16_t vp_id; struct qla_hw_data *ha = vha->hw; + unsigned long flags = 0; mutex_lock(&ha->vport_lock); + /* + * Wait for all pending activities to finish before removing vport from + * the list. + * Lock needs to be held for safe removal from the list (it + * ensures no active vp_list traversal while the vport is removed + * from the queue) + */ + spin_lock_irqsave(&ha->vport_slock, flags); + while (atomic_read(&vha->vref_count)) { + spin_unlock_irqrestore(&ha->vport_slock, flags); + + msleep(500); + + spin_lock_irqsave(&ha->vport_slock, flags); + } + list_del(&vha->list); + spin_unlock_irqrestore(&ha->vport_slock, flags); + vp_id = vha->vp_idx; ha->num_vhosts--; clear_bit(vp_id, ha->vp_idx_map); - list_del(&vha->list); + mutex_unlock(&ha->vport_lock); } @@ -68,12 +92,17 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) { scsi_qla_host_t *vha; struct scsi_qla_host *tvha; + unsigned long flags; + spin_lock_irqsave(&ha->vport_slock, flags); /* Locate matching device in database. */ list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { - if (!memcmp(port_name, vha->port_name, WWN_SIZE)) + if (!memcmp(port_name, vha->port_name, WWN_SIZE)) { + spin_unlock_irqrestore(&ha->vport_slock, flags); return vha; + } } + spin_unlock_irqrestore(&ha->vport_slock, flags); return NULL; } @@ -93,6 +122,12 @@ qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) static void qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) { + /* + * !!! NOTE !!! + * This function, if called in contexts other than vp create, disable + * or delete, please make sure this is synchronized with the + * delete thread. + */ fc_port_t *fcport; list_for_each_entry(fcport, &vha->vp_fcports, list) { @@ -100,7 +135,6 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) "loop_id=0x%04x :%x\n", vha->host_no, fcport->loop_id, fcport->vp_idx)); - atomic_set(&fcport->state, FCS_DEVICE_DEAD); qla2x00_mark_device_lost(vha, fcport, 0, 0); atomic_set(&fcport->state, FCS_UNCONFIGURED); } @@ -194,12 +228,17 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) void qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) { - scsi_qla_host_t *vha, *tvha; + scsi_qla_host_t *vha; struct qla_hw_data *ha = rsp->hw; int i = 0; + unsigned long flags; - list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vha, &ha->vp_list, list) { if (vha->vp_idx) { + atomic_inc(&vha->vref_count); + spin_unlock_irqrestore(&ha->vport_slock, flags); + switch (mb[0]) { case MBA_LIP_OCCURRED: case MBA_LOOP_UP: @@ -215,9 +254,13 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) qla2x00_async_event(vha, rsp, mb); break; } + + spin_lock_irqsave(&ha->vport_slock, flags); + atomic_dec(&vha->vref_count); } i++; } + spin_unlock_irqrestore(&ha->vport_slock, flags); } int @@ -297,7 +340,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) int ret; struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; - struct scsi_qla_host *tvp; + unsigned long flags = 0; if (vha->vp_idx) return; @@ -309,10 +352,19 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) if (!(ha->current_topology & ISP_CFG_F)) return; - list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { - if (vp->vp_idx) + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vp, &ha->vp_list, list) { + if (vp->vp_idx) { + atomic_inc(&vp->vref_count); + spin_unlock_irqrestore(&ha->vport_slock, flags); + ret = qla2x00_do_dpc_vp(vp); + + spin_lock_irqsave(&ha->vport_slock, flags); + atomic_dec(&vp->vref_count); + } } + spin_unlock_irqrestore(&ha->vport_slock, flags); } int diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 915b77a6e193..0a71cc71eab2 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -2672,6 +2672,19 @@ qla82xx_start_scsi(srb_t *sp) sufficient_dsds: req_cnt = 1; + if (req->cnt < (req_cnt + 2)) { + cnt = (uint16_t)RD_REG_DWORD_RELAXED( + ®->req_q_out[0]); + if (req->ring_index < cnt) + req->cnt = cnt - req->ring_index; + else + req->cnt = req->length - + (req->ring_index - cnt); + } + + if (req->cnt < (req_cnt + 2)) + goto queuing_error; + ctx = sp->ctx = mempool_alloc(ha->ctx_mempool, GFP_ATOMIC); if (!sp->ctx) { DEBUG(printk(KERN_INFO @@ -3307,16 +3320,19 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha) set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); } qla2xxx_wake_dpc(vha); + ha->flags.fw_hung = 1; if (ha->flags.mbox_busy) { - ha->flags.fw_hung = 1; ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, - "Due to fw hung, doing premature " - "completion of mbx command\n")); - complete(&ha->mbx_intr_comp); + "Due to fw hung, doing premature " + "completion of mbx command\n")); + if (test_bit(MBX_INTR_WAIT, + &ha->mbx_cmd_flags)) + complete(&ha->mbx_intr_comp); } } - } + } else + vha->seconds_since_last_heartbeat = 0; vha->fw_heartbeat_counter = fw_heartbeat_counter; } @@ -3418,13 +3434,15 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) "%s(): Adapter reset needed!\n", __func__); set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); + ha->flags.fw_hung = 1; if (ha->flags.mbox_busy) { - ha->flags.fw_hung = 1; ha->flags.mbox_int = 1; DEBUG2(qla_printk(KERN_ERR, ha, - "Need reset, doing premature " - "completion of mbx command\n")); - complete(&ha->mbx_intr_comp); + "Need reset, doing premature " + "completion of mbx command\n")); + if (test_bit(MBX_INTR_WAIT, + &ha->mbx_cmd_flags)) + complete(&ha->mbx_intr_comp); } } else { qla82xx_check_fw_alive(vha); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8c80b49ac1c4..1e4bff695254 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2341,16 +2341,28 @@ probe_out: static void qla2x00_remove_one(struct pci_dev *pdev) { - scsi_qla_host_t *base_vha, *vha, *temp; + scsi_qla_host_t *base_vha, *vha; struct qla_hw_data *ha; + unsigned long flags; base_vha = pci_get_drvdata(pdev); ha = base_vha->hw; - list_for_each_entry_safe(vha, temp, &ha->vp_list, list) { - if (vha && vha->fc_vport) + spin_lock_irqsave(&ha->vport_slock, flags); + list_for_each_entry(vha, &ha->vp_list, list) { + atomic_inc(&vha->vref_count); + + if (vha && vha->fc_vport) { + spin_unlock_irqrestore(&ha->vport_slock, flags); + fc_vport_terminate(vha->fc_vport); + + spin_lock_irqsave(&ha->vport_slock, flags); + } + + atomic_dec(&vha->vref_count); } + spin_unlock_irqrestore(&ha->vport_slock, flags); set_bit(UNLOADING, &base_vha->dpc_flags); @@ -2975,10 +2987,17 @@ static struct qla_work_evt * qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) { struct qla_work_evt *e; + uint8_t bail; + + QLA_VHA_MARK_BUSY(vha, bail); + if (bail) + return NULL; e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); - if (!e) + if (!e) { + QLA_VHA_MARK_NOT_BUSY(vha); return NULL; + } INIT_LIST_HEAD(&e->list); e->type = type; @@ -3135,6 +3154,9 @@ qla2x00_do_work(struct scsi_qla_host *vha) } if (e->flags & QLA_EVT_FLAG_FREE) kfree(e); + + /* For each work completed decrement vha ref count */ + QLA_VHA_MARK_NOT_BUSY(vha); } } diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e75ccb91317d..8edbccb3232d 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.03-k0" +#define QLA2XXX_VERSION "8.03.04-k0" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -#define QLA_DRIVER_PATCH_VER 3 +#define QLA_DRIVER_PATCH_VER 4 #define QLA_DRIVER_BETA_VER 0 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9ade720422c6..ee02d3838a0a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1011,8 +1011,8 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) err_exit: scsi_release_buffers(cmd); - scsi_put_command(cmd); cmd->request->special = NULL; + scsi_put_command(cmd); return error; } EXPORT_SYMBOL(scsi_init_io); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 63bd01ae534f..20514c47a5aa 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -870,7 +870,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); - if (atomic_dec_return(&sdkp->openers) && sdev->removable) { + if (atomic_dec_return(&sdkp->openers) == 0 && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } @@ -2623,15 +2623,15 @@ module_exit(exit_sd); static void sd_print_sense_hdr(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr) { - sd_printk(KERN_INFO, sdkp, ""); + sd_printk(KERN_INFO, sdkp, " "); scsi_show_sense_hdr(sshdr); - sd_printk(KERN_INFO, sdkp, ""); + sd_printk(KERN_INFO, sdkp, " "); scsi_show_extd_sense(sshdr->asc, sshdr->ascq); } static void sd_print_result(struct scsi_disk *sdkp, int result) { - sd_printk(KERN_INFO, sdkp, ""); + sd_printk(KERN_INFO, sdkp, " "); scsi_show_result(result); } diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a7bc8b7b09ac..2c3e89ddf069 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -72,10 +72,7 @@ static void sym_printl_hex(u_char *p, int n) static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg) { - if (label) - sym_print_addr(cp->cmd, "%s: ", label); - else - sym_print_addr(cp->cmd, ""); + sym_print_addr(cp->cmd, "%s: ", label); spi_print_msg(msg); printf("\n"); @@ -4558,7 +4555,8 @@ static void sym_int_sir(struct sym_hcb *np) switch (np->msgin [2]) { case M_X_MODIFY_DP: if (DEBUG_FLAGS & DEBUG_POINTER) - sym_print_msg(cp, NULL, np->msgin); + sym_print_msg(cp, "extended msg ", + np->msgin); tmp = (np->msgin[3]<<24) + (np->msgin[4]<<16) + (np->msgin[5]<<8) + (np->msgin[6]); sym_modify_dp(np, tp, cp, tmp); @@ -4585,7 +4583,7 @@ static void sym_int_sir(struct sym_hcb *np) */ case M_IGN_RESIDUE: if (DEBUG_FLAGS & DEBUG_POINTER) - sym_print_msg(cp, NULL, np->msgin); + sym_print_msg(cp, "1 or 2 byte ", np->msgin); if (cp->host_flags & HF_SENSE) OUTL_DSP(np, SCRIPTA_BA(np, clrack)); else diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 7356a56ac458..be0ebce36e54 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c @@ -869,7 +869,9 @@ static int get_serial_info(struct m68k_serial * info, tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; tmp.custom_divisor = info->custom_divisor; - copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; } @@ -882,7 +884,8 @@ static int set_serial_info(struct m68k_serial * info, if (!new_info) return -EFAULT; - copy_from_user(&new_serial,new_info,sizeof(new_serial)); + if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) + return -EFAULT; old_info = *info; if (!capable(CAP_SYS_ADMIN)) { @@ -943,8 +946,7 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value) status = 0; #endif local_irq_restore(flags); - put_user(status,value); - return 0; + return put_user(status, value); } /* @@ -999,27 +1001,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, send_break(info, arg ? arg*(100) : 250); return 0; case TIOCGSERIAL: - if (access_ok(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct))) - return get_serial_info(info, - (struct serial_struct *) arg); - return -EFAULT; + return get_serial_info(info, + (struct serial_struct *) arg); case TIOCSSERIAL: return set_serial_info(info, (struct serial_struct *) arg); case TIOCSERGETLSR: /* Get line status register */ - if (access_ok(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) - return get_lsr_info(info, (unsigned int *) arg); - return -EFAULT; + return get_lsr_info(info, (unsigned int *) arg); case TIOCSERGSTRUCT: - if (!access_ok(VERIFY_WRITE, (void *) arg, - sizeof(struct m68k_serial))) + if (copy_to_user((struct m68k_serial *) arg, + info, sizeof(struct m68k_serial))) return -EFAULT; - copy_to_user((struct m68k_serial *) arg, - info, sizeof(struct m68k_serial)); return 0; - default: return -ENOIOCTLCMD; } diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index b745792ec25a..eaafb98debed 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c @@ -203,13 +203,13 @@ static int __init parse_options(struct early_serial8250_device *device, if (mmio || mmio32) printk(KERN_INFO - "Early serial console at MMIO%s 0x%llu (options '%s')\n", + "Early serial console at MMIO%s 0x%llx (options '%s')\n", mmio32 ? "32" : "", (unsigned long long)port->mapbase, device->options); else printk(KERN_INFO - "Early serial console at I/O port 0x%lu (options '%s')\n", + "Early serial console at I/O port 0x%lx (options '%s')\n", port->iobase, device->options); diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 50441ffe8e38..2904aa044126 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -472,14 +472,9 @@ pl010_set_termios(struct uart_port *port, struct ktermios *termios, spin_unlock_irqrestore(&uap->port.lock, flags); } -static void pl010_set_ldisc(struct uart_port *port) +static void pl010_set_ldisc(struct uart_port *port, int new) { - int line = port->line; - - if (line >= port->state->port.tty->driver->num) - return; - - if (port->state->port.tty->ldisc->ops->num == N_PPS) { + if (new == N_PPS) { port->flags |= UPF_HARDPPS_CD; pl010_enable_ms(port); } else diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index e57fb3d228e2..5318dd3774ae 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c @@ -121,7 +121,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int size, int baud_rate) unsigned int sclk = get_sclk(); /* Set TCR1 and TCR2, TFSR is not enabled for uart */ - SPORT_PUT_TCR1(up, (ITFS | TLSBIT | ITCLK)); + SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); SPORT_PUT_TCR2(up, size + 1); pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c index bc9af503907f..5dff45c76d32 100644 --- a/drivers/serial/mfd.c +++ b/drivers/serial/mfd.c @@ -27,6 +27,7 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> +#include <linux/slab.h> #include <linux/serial_reg.h> #include <linux/circ_buf.h> #include <linux/delay.h> @@ -1423,7 +1424,6 @@ static void hsu_global_init(void) } phsu = hsu; - hsu_debugfs_init(hsu); return; @@ -1435,18 +1435,20 @@ err_free_region: static void serial_hsu_remove(struct pci_dev *pdev) { - struct hsu_port *hsu; - int i; + void *priv = pci_get_drvdata(pdev); + struct uart_hsu_port *up; - hsu = pci_get_drvdata(pdev); - if (!hsu) + if (!priv) return; - for (i = 0; i < 3; i++) - uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port); + /* For port 0/1/2, priv is the address of uart_hsu_port */ + if (pdev->device != 0x081E) { + up = priv; + uart_remove_one_port(&serial_hsu_reg, &up->port); + } pci_set_drvdata(pdev, NULL); - free_irq(hsu->irq, hsu); + free_irq(pdev->irq, priv); pci_disable_device(pdev); } diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 8dedb266f143..c4399e23565a 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -500,6 +500,7 @@ static int __init mpc512x_psc_fifoc_init(void) psc_fifoc = of_iomap(np, 0); if (!psc_fifoc) { pr_err("%s: Can't map FIFOC\n", __func__); + of_node_put(np); return -ENODEV; } diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c index f6ad1ecbff79..51c15f58e01e 100644 --- a/drivers/serial/mrst_max3110.c +++ b/drivers/serial/mrst_max3110.c @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/ioport.h> +#include <linux/irq.h> #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 141c69554bd4..7d475b2a79e8 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - link->resource[0]->end = 8; link->conf.Attributes = CONF_ENABLE_IRQ; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, /*====================================================================*/ +static int pfc_config(struct pcmcia_device *p_dev) +{ + unsigned int port = 0; + struct serial_info *info = p_dev->priv; + + if ((p_dev->resource[1]->end != 0) && + (resource_size(p_dev->resource[1]) == 8)) { + port = p_dev->resource[1]->start; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (resource_size(p_dev->resource[0]) == 0x40)) { + port = p_dev->resource[0]->start + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(p_dev, info, port, p_dev->irq); + + dev_warn(&p_dev->dev, "no usable port range found, giving up\n"); + return -ENODEV; +} + static int simple_config_check(struct pcmcia_device *p_dev, cistpl_cftable_entry_t *cf, cistpl_cftable_entry_t *dflt, @@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link) struct serial_info *info = link->priv; int i = -ENODEV, try; - /* If the card is already configured, look up the port and irq */ - if (link->function_config) { - unsigned int port = 0; - if ((link->resource[1]->end != 0) && - (resource_size(link->resource[1]) == 8)) { - port = link->resource[1]->end; - info->slave = 1; - } else if ((info->manfid == MANFID_OSITECH) && - (resource_size(link->resource[0]) == 0x40)) { - port = link->resource[0]->start + 0x28; - info->slave = 1; - } - if (info->slave) { - return setup_serial(link, info, port, - link->irq); - } - } + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; + link->resource[0]->end = 8; /* First pass: look for a config entry that looks normal. * Two tries: without IO aliases, then with aliases */ @@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link) if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) goto found_port; - printk(KERN_NOTICE - "serial_cs: no usable port range found, giving up\n"); + dev_warn(&link->dev, "no usable port range found, giving up\n"); return -1; found_port: @@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link) int i, base2 = 0; /* First, look for a generic full-sized window */ + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; link->resource[0]->end = info->multi * 8; if (pcmcia_loop_config(link, multi_config_check, &base2)) { /* If that didn't work, look for two windows */ @@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link) info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { - printk(KERN_NOTICE "serial_cs: no usable port range" + dev_warn(&link->dev, "no usable port range " "found, giving up\n"); return -ENODEV; } } if (!link->irq) - dev_warn(&link->dev, - "serial_cs: no usable IRQ found, continuing...\n"); + dev_warn(&link->dev, "no usable IRQ found, continuing...\n"); /* * Apply any configuration quirks. @@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link) multifunction cards that ask for appropriate IO port ranges */ if ((info->multi == 0) && (link->has_func_id) && + (link->socket->pcmcia_pfc == 0) && ((link->func_id == CISTPL_FUNCID_MULTI) || (link->func_id == CISTPL_FUNCID_SERIAL))) pcmcia_loop_config(link, serial_check_for_multi, info); @@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link) if (info->quirk && info->quirk->multi != -1) info->multi = info->quirk->multi; - if (info->multi > 1) + dev_info(&link->dev, + "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n", + link->manf_id, link->card_id, + link->socket->pcmcia_pfc, info->multi, info->quirk); + if (link->socket->pcmcia_pfc) + i = pfc_config(link); + else if (info->multi > 1) i = multi_config(link); else i = simple_config(link); @@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link) return 0; failed: - dev_warn(&link->dev, "serial_cs: failed to initialize\n"); + dev_warn(&link->dev, "failed to initialize\n"); serial_remove(link); return -ENODEV; } diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 7e5e5efea4e2..cff9a306660f 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -492,7 +492,7 @@ sn_receive_chars(struct sn_cons_port *port, unsigned long flags) sysrq_requested = 0; if (ch && time_before(jiffies, sysrq_timeout)) { spin_unlock_irqrestore(&port->sc_port.lock, flags); - handle_sysrq(ch, NULL); + handle_sysrq(ch); spin_lock_irqsave(&port->sc_port.lock, flags); /* ignore actual sysrq command char */ continue; diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c index acd35d1ebd12..4c37c4e28647 100644 --- a/drivers/spi/amba-pl022.c +++ b/drivers/spi/amba-pl022.c @@ -503,8 +503,9 @@ static void giveback(struct pl022 *pl022) msg->state = NULL; if (msg->complete) msg->complete(msg->context); - /* This message is completed, so let's turn off the clock! */ + /* This message is completed, so let's turn off the clocks! */ clk_disable(pl022->clk); + amba_pclk_disable(pl022->adev); } /** @@ -1139,9 +1140,10 @@ static void pump_messages(struct work_struct *work) /* Setup the SPI using the per chip configuration */ pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi); /* - * We enable the clock here, then the clock will be disabled when + * We enable the clocks here, then the clocks will be disabled when * giveback() is called in each method (poll/interrupt/DMA) */ + amba_pclk_enable(pl022->adev); clk_enable(pl022->clk); restore_state(pl022); flush(pl022); @@ -1786,11 +1788,9 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) } /* Disable SSP */ - clk_enable(pl022->clk); writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); load_ssp_default_config(pl022); - clk_disable(pl022->clk); status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022", pl022); @@ -1818,6 +1818,8 @@ pl022_probe(struct amba_device *adev, struct amba_id *id) goto err_spi_register; } dev_dbg(dev, "probe succeded\n"); + /* Disable the silicon block pclk and clock it when needed */ + amba_pclk_disable(adev); return 0; err_spi_register: @@ -1879,9 +1881,9 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state) return status; } - clk_enable(pl022->clk); + amba_pclk_enable(adev); load_ssp_default_config(pl022); - clk_disable(pl022->clk); + amba_pclk_disable(adev); dev_dbg(&adev->dev, "suspended\n"); return 0; } @@ -1981,7 +1983,7 @@ static int __init pl022_init(void) return amba_driver_register(&pl022_driver); } -module_init(pl022_init); +subsys_initcall(pl022_init); static void __exit pl022_exit(void) { diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c index d256cb00604c..56247853c298 100644 --- a/drivers/spi/dw_spi.c +++ b/drivers/spi/dw_spi.c @@ -181,10 +181,6 @@ static void flush(struct dw_spi *dws) wait_till_not_busy(dws); } -static void null_cs_control(u32 command) -{ -} - static int null_writer(struct dw_spi *dws) { u8 n_bytes = dws->n_bytes; @@ -322,7 +318,7 @@ static void giveback(struct dw_spi *dws) struct spi_transfer, transfer_list); - if (!last_transfer->cs_change) + if (!last_transfer->cs_change && dws->cs_control) dws->cs_control(MRST_SPI_DEASSERT); msg->state = NULL; @@ -396,6 +392,11 @@ static irqreturn_t interrupt_transfer(struct dw_spi *dws) static irqreturn_t dw_spi_irq(int irq, void *dev_id) { struct dw_spi *dws = dev_id; + u16 irq_status, irq_mask = 0x3f; + + irq_status = dw_readw(dws, isr) & irq_mask; + if (!irq_status) + return IRQ_NONE; if (!dws->cur_msg) { spi_mask_intr(dws, SPI_INT_TXEI); @@ -544,13 +545,13 @@ static void pump_transfers(unsigned long data) */ if (dws->cs_control) { if (dws->rx && dws->tx) - chip->tmode = 0x00; + chip->tmode = SPI_TMOD_TR; else if (dws->rx) - chip->tmode = 0x02; + chip->tmode = SPI_TMOD_RO; else - chip->tmode = 0x01; + chip->tmode = SPI_TMOD_TO; - cr0 &= ~(0x3 << SPI_MODE_OFFSET); + cr0 &= ~SPI_TMOD_MASK; cr0 |= (chip->tmode << SPI_TMOD_OFFSET); } @@ -699,9 +700,6 @@ static int dw_spi_setup(struct spi_device *spi) chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); if (!chip) return -ENOMEM; - - chip->cs_control = null_cs_control; - chip->enable_dma = 0; } /* @@ -883,7 +881,7 @@ int __devinit dw_spi_add_host(struct dw_spi *dws) dws->dma_inited = 0; dws->dma_addr = (dma_addr_t)(dws->paddr + 0x60); - ret = request_irq(dws->irq, dw_spi_irq, 0, + ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, "dw_spi", dws); if (ret < 0) { dev_err(&master->dev, "can not get IRQ\n"); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a9e5c79ae52a..b5a78a1f4421 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -23,6 +23,7 @@ #include <linux/init.h> #include <linux/cache.h> #include <linux/mutex.h> +#include <linux/of_device.h> #include <linux/slab.h> #include <linux/mod_devicetable.h> #include <linux/spi/spi.h> @@ -86,6 +87,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv) const struct spi_device *spi = to_spi_device(dev); const struct spi_driver *sdrv = to_spi_driver(drv); + /* Attempt an OF style match */ + if (of_driver_match_device(dev, drv)) + return 1; + if (sdrv->id_table) return !!spi_match_id(sdrv->id_table, spi); @@ -554,11 +559,9 @@ done: EXPORT_SYMBOL_GPL(spi_register_master); -static int __unregister(struct device *dev, void *master_dev) +static int __unregister(struct device *dev, void *null) { - /* note: before about 2.6.14-rc1 this would corrupt memory: */ - if (dev != master_dev) - spi_unregister_device(to_spi_device(dev)); + spi_unregister_device(to_spi_device(dev)); return 0; } @@ -576,8 +579,7 @@ void spi_unregister_master(struct spi_master *master) { int dummy; - dummy = device_for_each_child(master->dev.parent, &master->dev, - __unregister); + dummy = device_for_each_child(&master->dev, NULL, __unregister); device_unregister(&master->dev); } EXPORT_SYMBOL_GPL(spi_unregister_master); diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index e24a63498acb..63e51b011d50 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c @@ -350,7 +350,7 @@ static int __init spi_gpio_probe(struct platform_device *pdev) spi_gpio->bitbang.master = spi_master_get(master); spi_gpio->bitbang.chipselect = spi_gpio_chipselect; - if ((master_flags & (SPI_MASTER_NO_RX | SPI_MASTER_NO_RX)) == 0) { + if ((master_flags & (SPI_MASTER_NO_TX | SPI_MASTER_NO_RX)) == 0) { spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; diff --git a/drivers/spi/spi_mpc8xxx.c b/drivers/spi/spi_mpc8xxx.c index d31b57f7baaf..1dd86b835cd8 100644 --- a/drivers/spi/spi_mpc8xxx.c +++ b/drivers/spi/spi_mpc8xxx.c @@ -408,11 +408,17 @@ static void mpc8xxx_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) xfer_ofs = mspi->xfer_in_progress->len - mspi->count; - out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); + if (mspi->rx_dma == mspi->dma_dummy_rx) + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma); + else + out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); out_be16(&rx_bd->cbd_datlen, 0); out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); - out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); + if (mspi->tx_dma == mspi->dma_dummy_tx) + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma); + else + out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); out_be16(&tx_bd->cbd_datlen, xfer_len); out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | BD_SC_LAST); diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c index 97365815a729..c3038da2648a 100644 --- a/drivers/spi/spi_s3c64xx.c +++ b/drivers/spi/spi_s3c64xx.c @@ -200,6 +200,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) val = readl(regs + S3C64XX_SPI_STATUS); } while (TX_FIFO_LVL(val, sci) && loops--); + if (loops == 0) + dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n"); + /* Flush RxFIFO*/ loops = msecs_to_loops(1); do { @@ -210,6 +213,9 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) break; } while (loops--); + if (loops == 0) + dev_warn(&sdd->pdev->dev, "Timed out flushing RX FIFO\n"); + val = readl(regs + S3C64XX_SPI_CH_CFG); val &= ~S3C64XX_SPI_CH_SW_RST; writel(val, regs + S3C64XX_SPI_CH_CFG); @@ -320,16 +326,17 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, /* millisecs to xfer 'len' bytes @ 'cur_speed' */ ms = xfer->len * 8 * 1000 / sdd->cur_speed; - ms += 5; /* some tolerance */ + ms += 10; /* some tolerance */ if (dma_mode) { val = msecs_to_jiffies(ms) + 10; val = wait_for_completion_timeout(&sdd->xfer_completion, val); } else { + u32 status; val = msecs_to_loops(ms); do { - val = readl(regs + S3C64XX_SPI_STATUS); - } while (RX_FIFO_LVL(val, sci) < xfer->len && --val); + status = readl(regs + S3C64XX_SPI_STATUS); + } while (RX_FIFO_LVL(status, sci) < xfer->len && --val); } if (!val) @@ -447,8 +454,8 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) writel(val, regs + S3C64XX_SPI_CLK_CFG); } -void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, - int size, enum s3c2410_dma_buffresult res) +static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, + int size, enum s3c2410_dma_buffresult res) { struct s3c64xx_spi_driver_data *sdd = buf_id; unsigned long flags; @@ -467,8 +474,8 @@ void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id, spin_unlock_irqrestore(&sdd->lock, flags); } -void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, - int size, enum s3c2410_dma_buffresult res) +static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id, + int size, enum s3c2410_dma_buffresult res) { struct s3c64xx_spi_driver_data *sdd = buf_id; unsigned long flags; @@ -508,8 +515,9 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd, list_for_each_entry(xfer, &msg->transfers, transfer_list) { if (xfer->tx_buf != NULL) { - xfer->tx_dma = dma_map_single(dev, xfer->tx_buf, - xfer->len, DMA_TO_DEVICE); + xfer->tx_dma = dma_map_single(dev, + (void *)xfer->tx_buf, xfer->len, + DMA_TO_DEVICE); if (dma_mapping_error(dev, xfer->tx_dma)) { dev_err(dev, "dma_map_single Tx failed\n"); xfer->tx_dma = XFER_DMAADDR_INVALID; @@ -919,6 +927,13 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) return -ENODEV; } + sci = pdev->dev.platform_data; + if (!sci->src_clk_name) { + dev_err(&pdev->dev, + "Board init must call s3c64xx_spi_set_info()\n"); + return -EINVAL; + } + /* Check for availability of necessary resource */ dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -946,8 +961,6 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) return -ENOMEM; } - sci = pdev->dev.platform_data; - platform_set_drvdata(pdev, master); sdd = spi_master_get_devdata(master); @@ -1170,7 +1183,7 @@ static int __init s3c64xx_spi_init(void) { return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); } -module_init(s3c64xx_spi_init); +subsys_initcall(s3c64xx_spi_init); static void __exit s3c64xx_spi_exit(void) { diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 4a7a7a7f11b6..335311a98fdc 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -113,8 +113,6 @@ source "drivers/staging/vme/Kconfig" source "drivers/staging/memrar/Kconfig" -source "drivers/staging/sep/Kconfig" - source "drivers/staging/iio/Kconfig" source "drivers/staging/zram/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ca5c03eb3ce3..e3f1e1b6095e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -38,7 +38,6 @@ obj-$(CONFIG_FB_UDL) += udlfb/ obj-$(CONFIG_HYPERV) += hv/ obj-$(CONFIG_VME_BUS) += vme/ obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ -obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_ZRAM) += zram/ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index b4a8d5eb64fa..05ca15a6c9f8 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c @@ -267,6 +267,10 @@ static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr, if (atomic_read(&bat_priv->log_level) == log_level_tmp) return count; + bat_info(net_dev, "Changing log level from: %i to: %li\n", + atomic_read(&bat_priv->log_level), + log_level_tmp); + atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp); return count; } diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 92c216a56885..6e973a79aa25 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -30,7 +30,6 @@ #include "hash.h" #include <linux/if_arp.h> -#include <linux/netfilter_bridge.h> #define MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -129,6 +128,9 @@ static bool hardif_is_iface_up(struct batman_if *batman_if) static void update_mac_addresses(struct batman_if *batman_if) { + if (!batman_if || !batman_if->packet_buff) + return; + addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr); memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, @@ -194,8 +196,6 @@ static void hardif_activate_interface(struct net_device *net_dev, if (batman_if->if_status != IF_INACTIVE) return; - dev_hold(batman_if->net_dev); - update_mac_addresses(batman_if); batman_if->if_status = IF_TO_BE_ACTIVATED; @@ -222,8 +222,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev, (batman_if->if_status != IF_TO_BE_ACTIVATED)) return; - dev_put(batman_if->net_dev); - batman_if->if_status = IF_INACTIVE; bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev); @@ -318,11 +316,13 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) if (ret != 1) goto out; + dev_hold(net_dev); + batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); if (!batman_if) { pr_err("Can't add interface (%s): out of memory\n", net_dev->name); - goto out; + goto release_dev; } batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); @@ -336,6 +336,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev) batman_if->if_num = -1; batman_if->net_dev = net_dev; batman_if->if_status = IF_NOT_IN_USE; + batman_if->packet_buff = NULL; INIT_LIST_HEAD(&batman_if->list); check_known_mac_addr(batman_if->net_dev->dev_addr); @@ -346,6 +347,8 @@ free_dev: kfree(batman_if->dev); free_if: kfree(batman_if); +release_dev: + dev_put(net_dev); out: return NULL; } @@ -374,6 +377,7 @@ static void hardif_remove_interface(struct batman_if *batman_if) batman_if->if_status = IF_TO_BE_REMOVED; list_del_rcu(&batman_if->list); sysfs_del_hardif(&batman_if->hardif_obj); + dev_put(batman_if->net_dev); call_rcu(&batman_if->rcu, hardif_free_interface); } @@ -393,15 +397,13 @@ static int hard_if_event(struct notifier_block *this, /* FIXME: each batman_if will be attached to a softif */ struct bat_priv *bat_priv = netdev_priv(soft_device); - if (!batman_if) - batman_if = hardif_add_interface(net_dev); + if (!batman_if && event == NETDEV_REGISTER) + batman_if = hardif_add_interface(net_dev); if (!batman_if) goto out; switch (event) { - case NETDEV_REGISTER: - break; case NETDEV_UP: hardif_activate_interface(soft_device, bat_priv, batman_if); break; @@ -428,11 +430,6 @@ out: return NOTIFY_DONE; } -static int batman_skb_recv_finish(struct sk_buff *skb) -{ - return NF_ACCEPT; -} - /* receive a packet with the batman ethertype coming on a hard * interface */ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, @@ -442,8 +439,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, struct bat_priv *bat_priv = netdev_priv(soft_device); struct batman_packet *batman_packet; struct batman_if *batman_if; - struct net_device_stats *stats; - struct rtnl_link_stats64 temp; int ret; skb = skb_share_check(skb, GFP_ATOMIC); @@ -455,13 +450,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (atomic_read(&module_state) != MODULE_ACTIVE) goto err_free; - /* if netfilter/ebtables wants to block incoming batman - * packets then give them a chance to do so here */ - ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL, - batman_skb_recv_finish); - if (ret != 1) - goto err_out; - /* packet should hold at least type and version */ if (unlikely(skb_headlen(skb) < 2)) goto err_free; @@ -479,12 +467,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, if (batman_if->if_status != IF_ACTIVE) goto err_free; - stats = (struct net_device_stats *)dev_get_stats(skb->dev, &temp); - if (stats) { - stats->rx_packets++; - stats->rx_bytes += skb->len; - } - batman_packet = (struct batman_packet *)skb->data; if (batman_packet->version != COMPAT_VERSION) { diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index fc3d32c12729..3ae7dd2d2d4d 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -67,6 +67,7 @@ static int bat_socket_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&socket_client->queue_list); socket_client->queue_len = 0; socket_client->index = i; + socket_client->bat_priv = inode->i_private; spin_lock_init(&socket_client->lock); init_waitqueue_head(&socket_client->queue_wait); @@ -151,9 +152,8 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, static ssize_t bat_socket_write(struct file *file, const char __user *buff, size_t len, loff_t *off) { - /* FIXME: each orig_node->batman_if will be attached to a softif */ - struct bat_priv *bat_priv = netdev_priv(soft_device); struct socket_client *socket_client = file->private_data; + struct bat_priv *bat_priv = socket_client->bat_priv; struct icmp_packet_rr icmp_packet; struct orig_node *orig_node; struct batman_if *batman_if; @@ -168,6 +168,9 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, return -EINVAL; } + if (!bat_priv->primary_if) + return -EFAULT; + if (len >= sizeof(struct icmp_packet_rr)) packet_len = sizeof(struct icmp_packet_rr); @@ -223,7 +226,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (batman_if->if_status != IF_ACTIVE) goto dst_unreach; - memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet.orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); if (packet_len == sizeof(struct icmp_packet_rr)) memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); @@ -271,7 +275,7 @@ int bat_socket_setup(struct bat_priv *bat_priv) goto err; d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR, - bat_priv->debug_dir, NULL, &fops); + bat_priv->debug_dir, bat_priv, &fops); if (d) goto err; diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c index 2686019fe4e1..ef7c20ae7979 100644 --- a/drivers/staging/batman-adv/main.c +++ b/drivers/staging/batman-adv/main.c @@ -250,10 +250,13 @@ int choose_orig(void *data, int32_t size) int is_my_mac(uint8_t *addr) { struct batman_if *batman_if; + rcu_read_lock(); list_for_each_entry_rcu(batman_if, &if_list, list) { - if ((batman_if->net_dev) && - (compare_orig(batman_if->net_dev->dev_addr, addr))) { + if (batman_if->if_status != IF_ACTIVE) + continue; + + if (compare_orig(batman_if->net_dev->dev_addr, addr)) { rcu_read_unlock(); return 1; } diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index 28bb627ffa13..de5a8c1a8104 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -391,11 +391,12 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) { struct orig_node *orig_node; + unsigned long flags; HASHIT(hashit); /* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; @@ -404,11 +405,11 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) goto err; } - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return 0; err: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return -ENOMEM; } @@ -468,12 +469,13 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) { struct batman_if *batman_if_tmp; struct orig_node *orig_node; + unsigned long flags; HASHIT(hashit); int ret; /* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock(&orig_hash_lock); + spin_lock_irqsave(&orig_hash_lock, flags); while (hash_iterate(orig_hash, &hashit)) { orig_node = hashit.bucket->data; @@ -500,10 +502,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) rcu_read_unlock(); batman_if->if_num = -1; - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return 0; err: - spin_unlock(&orig_hash_lock); + spin_unlock_irqrestore(&orig_hash_lock, flags); return -ENOMEM; } diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 066cc9149bf1..032195e6de94 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -783,6 +783,8 @@ int recv_bat_packet(struct sk_buff *skb, static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) { + /* FIXME: each batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device); struct orig_node *orig_node; struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; @@ -801,6 +803,9 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) return NET_RX_DROP; } + if (!bat_priv->primary_if) + return NET_RX_DROP; + /* answer echo request (ping) */ /* get routing information */ spin_lock_irqsave(&orig_hash_lock, flags); @@ -830,7 +835,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) } memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); + memcpy(icmp_packet->orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL; @@ -845,6 +851,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len) static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) { + /* FIXME: each batman_if will be attached to a softif */ + struct bat_priv *bat_priv = netdev_priv(soft_device); struct orig_node *orig_node; struct icmp_packet *icmp_packet; struct ethhdr *ethhdr; @@ -865,6 +873,9 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) return NET_RX_DROP; } + if (!bat_priv->primary_if) + return NET_RX_DROP; + /* get routing information */ spin_lock_irqsave(&orig_hash_lock, flags); orig_node = ((struct orig_node *) @@ -892,7 +903,8 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len) } memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN); + memcpy(icmp_packet->orig, + bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL; diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index 055edee7b4e4..da3c82e47bbd 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -29,7 +29,6 @@ #include "vis.h" #include "aggregation.h" -#include <linux/netfilter_bridge.h> static void send_outstanding_bcast_packet(struct work_struct *work); @@ -92,12 +91,9 @@ int send_skb_packet(struct sk_buff *skb, /* dev_queue_xmit() returns a negative result on error. However on * congestion and traffic shaping, it drops and returns NET_XMIT_DROP - * (which is > 0). This will not be treated as an error. - * Also, if netfilter/ebtables wants to block outgoing batman - * packets then giving them a chance to do so here */ + * (which is > 0). This will not be treated as an error. */ - return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, - dev_queue_xmit); + return dev_queue_xmit(skb); send_skb_err: kfree_skb(skb); return NET_XMIT_DROP; diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 21d0717afb09..9aa9d369c752 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h @@ -126,6 +126,7 @@ struct socket_client { unsigned char index; spinlock_t lock; wait_queue_head_t queue_wait; + struct bat_priv *bat_priv; }; struct socket_packet { diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index c6aa52f8dcee..48d9fb1227df 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -222,7 +222,6 @@ static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(io->flags); - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; p_dev->resource[0]->start = io->win[0].base; p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 56e11575c977..64a01147ecae 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -327,6 +327,9 @@ static const struct net_device_ops device_ops = { .ndo_stop = netvsc_close, .ndo_start_xmit = netvsc_start_xmit, .ndo_set_multicast_list = netvsc_set_multicast_list, + .ndo_change_mtu = eth_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = eth_mac_addr, }; static int netvsc_probe(struct device *device) diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c index 17bc7626f70a..d78c569ac94a 100644 --- a/drivers/staging/hv/ring_buffer.c +++ b/drivers/staging/hv/ring_buffer.c @@ -193,8 +193,7 @@ Description: static inline u64 GetRingBufferIndices(struct hv_ring_buffer_info *RingInfo) { - return ((u64)RingInfo->RingBuffer->WriteIndex << 32) - || RingInfo->RingBuffer->ReadIndex; + return (u64)RingInfo->RingBuffer->WriteIndex << 32; } diff --git a/drivers/staging/hv/storvsc_api.h b/drivers/staging/hv/storvsc_api.h index 0063bde9a4b2..8505a1c5f9ee 100644 --- a/drivers/staging/hv/storvsc_api.h +++ b/drivers/staging/hv/storvsc_api.h @@ -28,10 +28,10 @@ #include "vmbus_api.h" /* Defines */ -#define STORVSC_RING_BUFFER_SIZE (10*PAGE_SIZE) +#define STORVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) #define BLKVSC_RING_BUFFER_SIZE (20*PAGE_SIZE) -#define STORVSC_MAX_IO_REQUESTS 64 +#define STORVSC_MAX_IO_REQUESTS 128 /* * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c index 075b61bd492f..62882a437aa4 100644 --- a/drivers/staging/hv/storvsc_drv.c +++ b/drivers/staging/hv/storvsc_drv.c @@ -495,7 +495,7 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ - if (j == 0) + if (bounce_addr == 0) bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); while (srclen) { @@ -556,7 +556,7 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, destlen = orig_sgl[i].length; /* ASSERT(orig_sgl[i].offset + orig_sgl[i].length <= PAGE_SIZE); */ - if (j == 0) + if (bounce_addr == 0) bounce_addr = (unsigned long)kmap_atomic(sg_page((&bounce_sgl[j])), KM_IRQ0); while (destlen) { @@ -615,6 +615,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, unsigned int request_size = 0; int i; struct scatterlist *sgl; + unsigned int sg_count = 0; DPRINT_DBG(STORVSC_DRV, "scmnd %p dir %d, use_sg %d buf %p len %d " "queue depth %d tagged %d", scmnd, scmnd->sc_data_direction, @@ -697,6 +698,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, request->DataBuffer.Length = scsi_bufflen(scmnd); if (scsi_sg_count(scmnd)) { sgl = (struct scatterlist *)scsi_sglist(scmnd); + sg_count = scsi_sg_count(scmnd); /* check if we need to bounce the sgl */ if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { @@ -731,15 +733,16 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd, scsi_sg_count(scmnd)); sgl = cmd_request->bounce_sgl; + sg_count = cmd_request->bounce_sgl_count; } request->DataBuffer.Offset = sgl[0].offset; - for (i = 0; i < scsi_sg_count(scmnd); i++) { + for (i = 0; i < sg_count; i++) { DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n", i, sgl[i].length, sgl[i].offset); request->DataBuffer.PfnArray[i] = - page_to_pfn(sg_page((&sgl[i]))); + page_to_pfn(sg_page((&sgl[i]))); } } else if (scsi_sglist(scmnd)) { /* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */ diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 638ad6b35891..9493128e5fd2 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig @@ -1,6 +1,6 @@ config OCTEON_ETHERNET tristate "Cavium Networks Octeon Ethernet support" - depends on CPU_CAVIUM_OCTEON + depends on CPU_CAVIUM_OCTEON && NETDEVICES select PHYLIB select MDIO_OCTEON help diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index a0fe31de0a6d..ebf9074a9083 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -44,6 +44,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x07B8, 0x2870)}, /* AboCom */ {USB_DEVICE(0x07B8, 0x2770)}, /* AboCom */ {USB_DEVICE(0x0DF6, 0x0039)}, /* Sitecom 2770 */ + {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom 2770 */ {USB_DEVICE(0x083A, 0x7512)}, /* Arcadyan 2770 */ {USB_DEVICE(0x0789, 0x0162)}, /* Logitec 2870 */ {USB_DEVICE(0x0789, 0x0163)}, /* Logitec 2870 */ @@ -95,7 +96,8 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x050d, 0x815c)}, {USB_DEVICE(0x1482, 0x3C09)}, /* Abocom */ {USB_DEVICE(0x14B2, 0x3C09)}, /* Alpha */ - {USB_DEVICE(0x04E8, 0x2018)}, /* samsung */ + {USB_DEVICE(0x04E8, 0x2018)}, /* samsung linkstick2 */ + {USB_DEVICE(0x1690, 0x0740)}, /* Askey */ {USB_DEVICE(0x5A57, 0x0280)}, /* Zinwell */ {USB_DEVICE(0x5A57, 0x0282)}, /* Zinwell */ {USB_DEVICE(0x7392, 0x7718)}, @@ -105,21 +107,34 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ + {USB_DEVICE(0x100D, 0x9031)}, /* Motorola 2770 */ #endif /* RT2870 // */ #ifdef RT3070 {USB_DEVICE(0x148F, 0x3070)}, /* Ralink 3070 */ {USB_DEVICE(0x148F, 0x3071)}, /* Ralink 3071 */ {USB_DEVICE(0x148F, 0x3072)}, /* Ralink 3072 */ {USB_DEVICE(0x0DB0, 0x3820)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x871C)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x822C)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x871B)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x822B)}, /* Ralink 3070 */ {USB_DEVICE(0x0DF6, 0x003E)}, /* Sitecom 3070 */ {USB_DEVICE(0x0DF6, 0x0042)}, /* Sitecom 3072 */ + {USB_DEVICE(0x0DF6, 0x0048)}, /* Sitecom 3070 */ + {USB_DEVICE(0x0DF6, 0x0047)}, /* Sitecom 3071 */ {USB_DEVICE(0x14B2, 0x3C12)}, /* AL 3070 */ {USB_DEVICE(0x18C5, 0x0012)}, /* Corega 3070 */ {USB_DEVICE(0x083A, 0x7511)}, /* Arcadyan 3070 */ + {USB_DEVICE(0x083A, 0xA701)}, /* SMC 3070 */ + {USB_DEVICE(0x083A, 0xA702)}, /* SMC 3072 */ {USB_DEVICE(0x1740, 0x9703)}, /* EnGenius 3070 */ {USB_DEVICE(0x1740, 0x9705)}, /* EnGenius 3071 */ {USB_DEVICE(0x1740, 0x9706)}, /* EnGenius 3072 */ + {USB_DEVICE(0x1740, 0x9707)}, /* EnGenius 3070 */ + {USB_DEVICE(0x1740, 0x9708)}, /* EnGenius 3071 */ + {USB_DEVICE(0x1740, 0x9709)}, /* EnGenius 3072 */ {USB_DEVICE(0x13D3, 0x3273)}, /* AzureWave 3070 */ + {USB_DEVICE(0x13D3, 0x3305)}, /* AzureWave 3070*/ {USB_DEVICE(0x1044, 0x800D)}, /* Gigabyte GN-WB32L 3070 */ {USB_DEVICE(0x2019, 0xAB25)}, /* Planex Communications, Inc. RT3070 */ {USB_DEVICE(0x07B8, 0x3070)}, /* AboCom 3070 */ @@ -132,14 +147,36 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x07D1, 0x3C0D)}, /* D-Link 3070 */ {USB_DEVICE(0x07D1, 0x3C0E)}, /* D-Link 3070 */ {USB_DEVICE(0x07D1, 0x3C0F)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C16)}, /* D-Link 3070 */ + {USB_DEVICE(0x07D1, 0x3C17)}, /* D-Link 8070 */ {USB_DEVICE(0x1D4D, 0x000C)}, /* Pegatron Corporation 3070 */ {USB_DEVICE(0x1D4D, 0x000E)}, /* Pegatron Corporation 3070 */ {USB_DEVICE(0x5A57, 0x5257)}, /* Zinwell 3070 */ {USB_DEVICE(0x5A57, 0x0283)}, /* Zinwell 3072 */ {USB_DEVICE(0x04BB, 0x0945)}, /* I-O DATA 3072 */ + {USB_DEVICE(0x04BB, 0x0947)}, /* I-O DATA 3070 */ + {USB_DEVICE(0x04BB, 0x0948)}, /* I-O DATA 3072 */ {USB_DEVICE(0x203D, 0x1480)}, /* Encore 3070 */ + {USB_DEVICE(0x20B8, 0x8888)}, /* PARA INDUSTRIAL 3070 */ + {USB_DEVICE(0x0B05, 0x1784)}, /* Asus 3072 */ + {USB_DEVICE(0x203D, 0x14A9)}, /* Encore 3070*/ + {USB_DEVICE(0x0DB0, 0x899A)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x3870)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x870A)}, /* MSI 3070*/ + {USB_DEVICE(0x0DB0, 0x6899)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3822)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3871)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x871A)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x822A)}, /* MSI 3070 */ + {USB_DEVICE(0x0DB0, 0x3821)}, /* Ralink 3070 */ + {USB_DEVICE(0x0DB0, 0x821A)}, /* Ralink 3070 */ + {USB_DEVICE(0x083A, 0xA703)}, /* IO-MAGIC */ + {USB_DEVICE(0x13D3, 0x3307)}, /* Azurewave */ + {USB_DEVICE(0x13D3, 0x3321)}, /* Azurewave */ + {USB_DEVICE(0x07FA, 0x7712)}, /* Edimax */ + {USB_DEVICE(0x0789, 0x0166)}, /* Edimax */ + {USB_DEVICE(0x148F, 0x2070)}, /* Edimax */ #endif /* RT3070 // */ - {USB_DEVICE(0x0DF6, 0x003F)}, /* Sitecom WL-608 */ {USB_DEVICE(0x1737, 0x0077)}, /* Linksys WUSB54GC-EU v3 */ {USB_DEVICE(0x2001, 0x3C09)}, /* D-Link */ {USB_DEVICE(0x2001, 0x3C0A)}, /* D-Link 3072 */ diff --git a/drivers/staging/sep/Kconfig b/drivers/staging/sep/Kconfig deleted file mode 100644 index 0a9c39c7f2bd..000000000000 --- a/drivers/staging/sep/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config DX_SEP - tristate "Discretix SEP driver" -# depends on MRST - depends on RAR_REGISTER && PCI - default y - help - Discretix SEP driver - - If unsure say M. The compiled module will be - called sep_driver.ko diff --git a/drivers/staging/sep/Makefile b/drivers/staging/sep/Makefile deleted file mode 100644 index 628d5f919414..000000000000 --- a/drivers/staging/sep/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-$(CONFIG_DX_SEP) := sep_driver.o - diff --git a/drivers/staging/sep/TODO b/drivers/staging/sep/TODO deleted file mode 100644 index ff0e931dab64..000000000000 --- a/drivers/staging/sep/TODO +++ /dev/null @@ -1,8 +0,0 @@ -Todo's so far (from Alan Cox) -- Fix firmware loading -- Get firmware into firmware git tree -- Review and tidy each algorithm function -- Check whether it can be plugged into any of the kernel crypto API - interfaces -- Do something about the magic shared memory interface and replace it - with something saner (in Linux terms) diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h deleted file mode 100644 index 9200524bb64d..000000000000 --- a/drivers/staging/sep/sep_dev.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef __SEP_DEV_H__ -#define __SEP_DEV_H__ - -/* - * - * sep_dev.h - Security Processor Device Structures - * - * Copyright(c) 2009 Intel Corporation. All rights reserved. - * Copyright(c) 2009 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; 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. - * - * CONTACTS: - * - * Alan Cox alan@linux.intel.com - * - */ - -struct sep_device { - /* pointer to pci dev */ - struct pci_dev *pdev; - - unsigned long in_use; - - /* address of the shared memory allocated during init for SEP driver - (coherent alloc) */ - void *shared_addr; - /* the physical address of the shared area */ - dma_addr_t shared_bus; - - /* restricted access region (coherent alloc) */ - dma_addr_t rar_bus; - void *rar_addr; - /* firmware regions: cache is at rar_addr */ - unsigned long cache_size; - - /* follows the cache */ - dma_addr_t resident_bus; - unsigned long resident_size; - void *resident_addr; - - /* start address of the access to the SEP registers from driver */ - void __iomem *reg_addr; - /* transaction counter that coordinates the transactions between SEP and HOST */ - unsigned long send_ct; - /* counter for the messages from sep */ - unsigned long reply_ct; - /* counter for the number of bytes allocated in the pool for the current - transaction */ - unsigned long data_pool_bytes_allocated; - - /* array of pointers to the pages that represent input data for the synchronic - DMA action */ - struct page **in_page_array; - - /* array of pointers to the pages that represent out data for the synchronic - DMA action */ - struct page **out_page_array; - - /* number of pages in the sep_in_page_array */ - unsigned long in_num_pages; - - /* number of pages in the sep_out_page_array */ - unsigned long out_num_pages; - - /* global data for every flow */ - struct sep_flow_context_t flows[SEP_DRIVER_NUM_FLOWS]; - - /* pointer to the workqueue that handles the flow done interrupts */ - struct workqueue_struct *flow_wq; - -}; - -static struct sep_device *sep_dev; - -static inline void sep_write_reg(struct sep_device *dev, int reg, u32 value) -{ - void __iomem *addr = dev->reg_addr + reg; - writel(value, addr); -} - -static inline u32 sep_read_reg(struct sep_device *dev, int reg) -{ - void __iomem *addr = dev->reg_addr + reg; - return readl(addr); -} - -/* wait for SRAM write complete(indirect write */ -static inline void sep_wait_sram_write(struct sep_device *dev) -{ - u32 reg_val; - do - reg_val = sep_read_reg(dev, HW_SRAM_DATA_READY_REG_ADDR); - while (!(reg_val & 1)); -} - - -#endif diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c deleted file mode 100644 index ecbde3467b1b..000000000000 --- a/drivers/staging/sep/sep_driver.c +++ /dev/null @@ -1,2742 +0,0 @@ -/* - * - * sep_driver.c - Security Processor Driver main group of functions - * - * Copyright(c) 2009 Intel Corporation. All rights reserved. - * Copyright(c) 2009 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; 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. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/cdev.h> -#include <linux/kdev_t.h> -#include <linux/mutex.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/poll.h> -#include <linux/wait.h> -#include <linux/pci.h> -#include <linux/firmware.h> -#include <linux/slab.h> -#include <asm/ioctl.h> -#include <linux/ioport.h> -#include <asm/io.h> -#include <linux/interrupt.h> -#include <linux/pagemap.h> -#include <asm/cacheflush.h> -#include "sep_driver_hw_defs.h" -#include "sep_driver_config.h" -#include "sep_driver_api.h" -#include "sep_dev.h" - -#if SEP_DRIVER_ARM_DEBUG_MODE - -#define CRYS_SEP_ROM_length 0x4000 -#define CRYS_SEP_ROM_start_address 0x8000C000UL -#define CRYS_SEP_ROM_start_address_offset 0xC000UL -#define SEP_ROM_BANK_register 0x80008420UL -#define SEP_ROM_BANK_register_offset 0x8420UL -#define SEP_RAR_IO_MEM_REGION_START_ADDRESS 0x82000000 - -/* - * THESE 2 definitions are specific to the board - must be - * defined during integration - */ -#define SEP_RAR_IO_MEM_REGION_START_ADDRESS 0xFF0D0000 - -/* 2M size */ - -static void sep_load_rom_code(struct sep_device *sep) -{ - /* Index variables */ - unsigned long i, k, j; - u32 reg; - u32 error; - u32 warning; - - /* Loading ROM from SEP_ROM_image.h file */ - k = sizeof(CRYS_SEP_ROM); - - edbg("SEP Driver: DX_CC_TST_SepRomLoader start\n"); - - edbg("SEP Driver: k is %lu\n", k); - edbg("SEP Driver: sep->reg_addr is %p\n", sep->reg_addr); - edbg("SEP Driver: CRYS_SEP_ROM_start_address_offset is %p\n", CRYS_SEP_ROM_start_address_offset); - - for (i = 0; i < 4; i++) { - /* write bank */ - sep_write_reg(sep, SEP_ROM_BANK_register_offset, i); - - for (j = 0; j < CRYS_SEP_ROM_length / 4; j++) { - sep_write_reg(sep, CRYS_SEP_ROM_start_address_offset + 4 * j, CRYS_SEP_ROM[i * 0x1000 + j]); - - k = k - 4; - - if (k == 0) { - j = CRYS_SEP_ROM_length; - i = 4; - } - } - } - - /* reset the SEP */ - sep_write_reg(sep, HW_HOST_SEP_SW_RST_REG_ADDR, 0x1); - - /* poll for SEP ROM boot finish */ - do - reg = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); - while (!reg); - - edbg("SEP Driver: ROM polling ended\n"); - - switch (reg) { - case 0x1: - /* fatal error - read erro status from GPRO */ - error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR); - edbg("SEP Driver: ROM polling case 1\n"); - break; - case 0x4: - /* Cold boot ended successfully */ - case 0x8: - /* Warmboot ended successfully */ - case 0x10: - /* ColdWarm boot ended successfully */ - error = 0; - case 0x2: - /* Boot First Phase ended */ - warning = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR); - case 0x20: - edbg("SEP Driver: ROM polling case %d\n", reg); - break; - } - -} - -#else -static void sep_load_rom_code(struct sep_device *sep) { } -#endif /* SEP_DRIVER_ARM_DEBUG_MODE */ - - - -/*---------------------------------------- - DEFINES ------------------------------------------*/ - -#define BASE_ADDRESS_FOR_SYSTEM 0xfffc0000 -#define SEP_RAR_IO_MEM_REGION_SIZE 0x40000 - -/*-------------------------------------------- - GLOBAL variables ---------------------------------------------*/ - -/* debug messages level */ -static int debug; -module_param(debug, int , 0); -MODULE_PARM_DESC(debug, "Flag to enable SEP debug messages"); - -/* Keep this a single static object for now to keep the conversion easy */ - -static struct sep_device sep_instance; -static struct sep_device *sep_dev = &sep_instance; - -/* - mutex for the access to the internals of the sep driver -*/ -static DEFINE_MUTEX(sep_mutex); - - -/* wait queue head (event) of the driver */ -static DECLARE_WAIT_QUEUE_HEAD(sep_event); - -/** - * sep_load_firmware - copy firmware cache/resident - * @sep: device we are loading - * - * This functions copies the cache and resident from their source - * location into destination shared memory. - */ - -static int sep_load_firmware(struct sep_device *sep) -{ - const struct firmware *fw; - char *cache_name = "sep/cache.image.bin"; - char *res_name = "sep/resident.image.bin"; - int error; - - edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr); - edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus); - - /* load cache */ - error = request_firmware(&fw, cache_name, &sep->pdev->dev); - if (error) { - edbg("SEP Driver:cant request cache fw\n"); - return error; - } - edbg("SEP Driver:cache %08Zx@%p\n", fw->size, (void *) fw->data); - - memcpy(sep->rar_addr, (void *)fw->data, fw->size); - sep->cache_size = fw->size; - release_firmware(fw); - - sep->resident_bus = sep->rar_bus + sep->cache_size; - sep->resident_addr = sep->rar_addr + sep->cache_size; - - /* load resident */ - error = request_firmware(&fw, res_name, &sep->pdev->dev); - if (error) { - edbg("SEP Driver:cant request res fw\n"); - return error; - } - edbg("sep: res %08Zx@%p\n", fw->size, (void *)fw->data); - - memcpy(sep->resident_addr, (void *) fw->data, fw->size); - sep->resident_size = fw->size; - release_firmware(fw); - - edbg("sep: resident v %p b %08llx cache v %p b %08llx\n", - sep->resident_addr, (unsigned long long)sep->resident_bus, - sep->rar_addr, (unsigned long long)sep->rar_bus); - return 0; -} - -MODULE_FIRMWARE("sep/cache.image.bin"); -MODULE_FIRMWARE("sep/resident.image.bin"); - -/** - * sep_map_and_alloc_shared_area - allocate shared block - * @sep: security processor - * @size: size of shared area - * - * Allocate a shared buffer in host memory that can be used by both the - * kernel and also the hardware interface via DMA. - */ - -static int sep_map_and_alloc_shared_area(struct sep_device *sep, - unsigned long size) -{ - /* shared_addr = ioremap_nocache(0xda00000,shared_area_size); */ - sep->shared_addr = dma_alloc_coherent(&sep->pdev->dev, size, - &sep->shared_bus, GFP_KERNEL); - - if (!sep->shared_addr) { - edbg("sep_driver :shared memory dma_alloc_coherent failed\n"); - return -ENOMEM; - } - /* set the bus address of the shared area */ - edbg("sep: shared_addr %ld bytes @%p (bus %08llx)\n", - size, sep->shared_addr, (unsigned long long)sep->shared_bus); - return 0; -} - -/** - * sep_unmap_and_free_shared_area - free shared block - * @sep: security processor - * - * Free the shared area allocated to the security processor. The - * processor must have finished with this and any final posted - * writes cleared before we do so. - */ -static void sep_unmap_and_free_shared_area(struct sep_device *sep, int size) -{ - dma_free_coherent(&sep->pdev->dev, size, - sep->shared_addr, sep->shared_bus); -} - -/** - * sep_shared_virt_to_bus - convert bus/virt addresses - * - * Returns the bus address inside the shared area according - * to the virtual address. - */ - -static dma_addr_t sep_shared_virt_to_bus(struct sep_device *sep, - void *virt_address) -{ - dma_addr_t pa = sep->shared_bus + (virt_address - sep->shared_addr); - edbg("sep: virt to bus b %08llx v %p\n", (unsigned long long) pa, - virt_address); - return pa; -} - -/** - * sep_shared_bus_to_virt - convert bus/virt addresses - * - * Returns virtual address inside the shared area according - * to the bus address. - */ - -static void *sep_shared_bus_to_virt(struct sep_device *sep, - dma_addr_t bus_address) -{ - return sep->shared_addr + (bus_address - sep->shared_bus); -} - - -/** - * sep_try_open - attempt to open a SEP device - * @sep: device to attempt to open - * - * Atomically attempt to get ownership of a SEP device. - * Returns 1 if the device was opened, 0 on failure. - */ - -static int sep_try_open(struct sep_device *sep) -{ - if (!test_and_set_bit(0, &sep->in_use)) - return 1; - return 0; -} - -/** - * sep_open - device open method - * @inode: inode of sep device - * @filp: file handle to sep device - * - * Open method for the SEP device. Called when userspace opens - * the SEP device node. Must also release the memory data pool - * allocations. - * - * Returns zero on success otherwise an error code. - */ - -static int sep_open(struct inode *inode, struct file *filp) -{ - if (sep_dev == NULL) - return -ENODEV; - - /* check the blocking mode */ - if (filp->f_flags & O_NDELAY) { - if (sep_try_open(sep_dev) == 0) - return -EAGAIN; - } else - if (wait_event_interruptible(sep_event, sep_try_open(sep_dev)) < 0) - return -EINTR; - - /* Bind to the device, we only have one which makes it easy */ - filp->private_data = sep_dev; - /* release data pool allocations */ - sep_dev->data_pool_bytes_allocated = 0; - return 0; -} - - -/** - * sep_release - close a SEP device - * @inode: inode of SEP device - * @filp: file handle being closed - * - * Called on the final close of a SEP device. As the open protects against - * multiple simultaenous opens that means this method is called when the - * final reference to the open handle is dropped. - */ - -static int sep_release(struct inode *inode, struct file *filp) -{ - struct sep_device *sep = filp->private_data; -#if 0 /*!SEP_DRIVER_POLLING_MODE */ - /* close IMR */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF); - /* release IRQ line */ - free_irq(SEP_DIRVER_IRQ_NUM, sep); - -#endif - /* Ensure any blocked open progresses */ - clear_bit(0, &sep->in_use); - wake_up(&sep_event); - return 0; -} - -/*--------------------------------------------------------------- - map function - this functions maps the message shared area ------------------------------------------------------------------*/ -static int sep_mmap(struct file *filp, struct vm_area_struct *vma) -{ - dma_addr_t bus_addr; - struct sep_device *sep = filp->private_data; - - dbg("-------->SEP Driver: mmap start\n"); - - /* check that the size of the mapped range is as the size of the message - shared area */ - if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) { - edbg("SEP Driver mmap requested size is more than allowed\n"); - printk(KERN_WARNING "SEP Driver mmap requested size is more than allowed\n"); - printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end); - printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start); - return -EAGAIN; - } - - edbg("SEP Driver:sep->shared_addr is %p\n", sep->shared_addr); - - /* get bus address */ - bus_addr = sep->shared_bus; - - edbg("SEP Driver: phys_addr is %08llx\n", (unsigned long long)bus_addr); - - if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { - edbg("SEP Driver remap_page_range failed\n"); - printk(KERN_WARNING "SEP Driver remap_page_range failed\n"); - return -EAGAIN; - } - - dbg("SEP Driver:<-------- mmap end\n"); - - return 0; -} - - -/*----------------------------------------------- - poll function -*----------------------------------------------*/ -static unsigned int sep_poll(struct file *filp, poll_table * wait) -{ - unsigned long count; - unsigned int mask = 0; - unsigned long retval = 0; /* flow id */ - struct sep_device *sep = filp->private_data; - - dbg("---------->SEP Driver poll: start\n"); - - -#if SEP_DRIVER_POLLING_MODE - - while (sep->send_ct != (retval & 0x7FFFFFFF)) { - retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - - for (count = 0; count < 10 * 4; count += 4) - edbg("Poll Debug Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count))); - } - - sep->reply_ct++; -#else - /* add the event to the polling wait table */ - poll_wait(filp, &sep_event, wait); - -#endif - - edbg("sep->send_ct is %lu\n", sep->send_ct); - edbg("sep->reply_ct is %lu\n", sep->reply_ct); - - /* check if the data is ready */ - if (sep->send_ct == sep->reply_ct) { - for (count = 0; count < 12 * 4; count += 4) - edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + count))); - - for (count = 0; count < 10 * 4; count += 4) - edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep->shared_addr + 0x1800 + count))); - - retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR2_REG_ADDR); - edbg("retval is %lu\n", retval); - /* check if the this is sep reply or request */ - if (retval >> 31) { - edbg("SEP Driver: sep request in\n"); - /* request */ - mask |= POLLOUT | POLLWRNORM; - } else { - edbg("SEP Driver: sep reply in\n"); - mask |= POLLIN | POLLRDNORM; - } - } - dbg("SEP Driver:<-------- poll exit\n"); - return mask; -} - -/** - * sep_time_address - address in SEP memory of time - * @sep: SEP device we want the address from - * - * Return the address of the two dwords in memory used for time - * setting. - */ - -static u32 *sep_time_address(struct sep_device *sep) -{ - return sep->shared_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES; -} - -/** - * sep_set_time - set the SEP time - * @sep: the SEP we are setting the time for - * - * Calculates time and sets it at the predefined address. - * Called with the sep mutex held. - */ -static unsigned long sep_set_time(struct sep_device *sep) -{ - struct timeval time; - u32 *time_addr; /* address of time as seen by the kernel */ - - - dbg("sep:sep_set_time start\n"); - - do_gettimeofday(&time); - - /* set value in the SYSTEM MEMORY offset */ - time_addr = sep_time_address(sep); - - time_addr[0] = SEP_TIME_VAL_TOKEN; - time_addr[1] = time.tv_sec; - - edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec); - edbg("SEP Driver:time_addr is %p\n", time_addr); - edbg("SEP Driver:sep->shared_addr is %p\n", sep->shared_addr); - - return time.tv_sec; -} - -/** - * sep_dump_message - dump the message that is pending - * @sep: sep device - * - * Dump out the message pending in the shared message area - */ - -static void sep_dump_message(struct sep_device *sep) -{ - int count; - for (count = 0; count < 12 * 4; count += 4) - edbg("Word %d of the message is %u\n", count, *((u32 *) (sep->shared_addr + count))); -} - -/** - * sep_send_command_handler - kick off a command - * @sep: sep being signalled - * - * This function raises interrupt to SEP that signals that is has a new - * command from the host - */ - -static void sep_send_command_handler(struct sep_device *sep) -{ - dbg("sep:sep_send_command_handler start\n"); - - mutex_lock(&sep_mutex); - sep_set_time(sep); - - /* FIXME: flush cache */ - flush_cache_all(); - - sep_dump_message(sep); - /* update counter */ - sep->send_ct++; - /* send interrupt to SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); - dbg("SEP Driver:<-------- sep_send_command_handler end\n"); - mutex_unlock(&sep_mutex); - return; -} - -/** - * sep_send_reply_command_handler - kick off a command reply - * @sep: sep being signalled - * - * This function raises interrupt to SEP that signals that is has a new - * command from the host - */ - -static void sep_send_reply_command_handler(struct sep_device *sep) -{ - dbg("sep:sep_send_reply_command_handler start\n"); - - /* flash cache */ - flush_cache_all(); - - sep_dump_message(sep); - - mutex_lock(&sep_mutex); - sep->send_ct++; /* update counter */ - /* send the interrupt to SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep->send_ct); - /* update both counters */ - sep->send_ct++; - sep->reply_ct++; - mutex_unlock(&sep_mutex); - dbg("sep: sep_send_reply_command_handler end\n"); -} - -/* - This function handles the allocate data pool memory request - This function returns calculates the bus address of the - allocated memory, and the offset of this area from the mapped address. - Therefore, the FVOs in user space can calculate the exact virtual - address of this allocated memory -*/ -static int sep_allocate_data_pool_memory_handler(struct sep_device *sep, - unsigned long arg) -{ - int error; - struct sep_driver_alloc_t command_args; - - dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n"); - - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - /* allocate memory */ - if ((sep->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { - error = -ENOMEM; - goto end_function; - } - - /* set the virtual and bus address */ - command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep->data_pool_bytes_allocated; - command_args.phys_address = sep->shared_bus + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep->data_pool_bytes_allocated; - - /* write the memory back to the user space */ - error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - /* set the allocation */ - sep->data_pool_bytes_allocated += command_args.num_bytes; - -end_function: - dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n"); - return error; -} - -/* - This function handles write into allocated data pool command -*/ -static int sep_write_into_data_pool_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - void *virt_address; - unsigned long va; - unsigned long app_in_address; - unsigned long num_bytes; - void *data_pool_area_addr; - - dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n"); - - /* get the application address */ - error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address)); - if (error) - goto end_function; - - /* get the virtual kernel address address */ - error = get_user(va, &(((struct sep_driver_write_t *) arg)->datapool_address)); - if (error) - goto end_function; - virt_address = (void *)va; - - /* get the number of bytes */ - error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes)); - if (error) - goto end_function; - - /* calculate the start of the data pool */ - data_pool_area_addr = sep->shared_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES; - - - /* check that the range of the virtual kernel address is correct */ - if (virt_address < data_pool_area_addr || virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES)) { - error = -EINVAL; - goto end_function; - } - /* copy the application data */ - error = copy_from_user(virt_address, (void *) app_in_address, num_bytes); - if (error) - error = -EFAULT; -end_function: - dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n"); - return error; -} - -/* - this function handles the read from data pool command -*/ -static int sep_read_from_data_pool_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - /* virtual address of dest application buffer */ - unsigned long app_out_address; - /* virtual address of the data pool */ - unsigned long va; - void *virt_address; - unsigned long num_bytes; - void *data_pool_area_addr; - - dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n"); - - /* get the application address */ - error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address)); - if (error) - goto end_function; - - /* get the virtual kernel address address */ - error = get_user(va, &(((struct sep_driver_write_t *) arg)->datapool_address)); - if (error) - goto end_function; - virt_address = (void *)va; - - /* get the number of bytes */ - error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes)); - if (error) - goto end_function; - - /* calculate the start of the data pool */ - data_pool_area_addr = sep->shared_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES; - - /* FIXME: These are incomplete all over the driver: what about + len - and when doing that also overflows */ - /* check that the range of the virtual kernel address is correct */ - if (virt_address < data_pool_area_addr || virt_address > data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) { - error = -EINVAL; - goto end_function; - } - - /* copy the application data */ - error = copy_to_user((void *) app_out_address, virt_address, num_bytes); - if (error) - error = -EFAULT; -end_function: - dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n"); - return error; -} - -/* - This function releases all the application virtual buffer physical pages, - that were previously locked -*/ -static int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag) -{ - unsigned long count; - - if (dirtyFlag) { - for (count = 0; count < num_pages; count++) { - /* the out array was written, therefore the data was changed */ - if (!PageReserved(page_array_ptr[count])) - SetPageDirty(page_array_ptr[count]); - page_cache_release(page_array_ptr[count]); - } - } else { - /* free in pages - the data was only read, therefore no update was done - on those pages */ - for (count = 0; count < num_pages; count++) - page_cache_release(page_array_ptr[count]); - } - - if (page_array_ptr) - /* free the array */ - kfree(page_array_ptr); - - return 0; -} - -/* - This function locks all the physical pages of the kernel virtual buffer - and construct a basic lli array, where each entry holds the physical - page address and the size that application data holds in this physical pages -*/ -static int sep_lock_kernel_pages(struct sep_device *sep, - unsigned long kernel_virt_addr, - unsigned long data_size, - unsigned long *num_pages_ptr, - struct sep_lli_entry_t **lli_array_ptr, - struct page ***page_array_ptr) -{ - int error = 0; - /* the the page of the end address of the user space buffer */ - unsigned long end_page; - /* the page of the start address of the user space buffer */ - unsigned long start_page; - /* the range in pages */ - unsigned long num_pages; - struct sep_lli_entry_t *lli_array; - /* next kernel address to map */ - unsigned long next_kernel_address; - unsigned long count; - - dbg("SEP Driver:--------> sep_lock_kernel_pages start\n"); - - /* set start and end pages and num pages */ - end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = kernel_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; - - edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr); - edbg("SEP Driver: data_size is %lu\n", data_size); - edbg("SEP Driver: start_page is %lx\n", start_page); - edbg("SEP Driver: end_page is %lx\n", end_page); - edbg("SEP Driver: num_pages is %lu\n", num_pages); - - lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC); - if (!lli_array) { - edbg("SEP Driver: kmalloc for lli_array failed\n"); - error = -ENOMEM; - goto end_function; - } - - /* set the start address of the first page - app data may start not at - the beginning of the page */ - lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr); - - /* check that not all the data is in the first page only */ - if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; - else - lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK)); - - /* debug print */ - dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size); - - /* advance the address to the start of the next page */ - next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE; - - /* go from the second page to the prev before last */ - for (count = 1; count < (num_pages - 1); count++) { - lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address); - lli_array[count].block_size = PAGE_SIZE; - - edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size); - next_kernel_address += PAGE_SIZE; - } - - /* if more then 1 pages locked - then update for the last page size needed */ - if (num_pages > 1) { - /* update the address of the last page */ - lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address); - - /* set the size of the last page */ - lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK); - - if (lli_array[count].block_size == 0) { - dbg("app_virt_addr is %08lx\n", kernel_virt_addr); - dbg("data_size is %lu\n", data_size); - while (1); - } - - edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size); - } - /* set output params */ - *lli_array_ptr = lli_array; - *num_pages_ptr = num_pages; - *page_array_ptr = 0; -end_function: - dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n"); - return 0; -} - -/* - This function locks all the physical pages of the application virtual buffer - and construct a basic lli array, where each entry holds the physical page - address and the size that application data holds in this physical pages -*/ -static int sep_lock_user_pages(struct sep_device *sep, - unsigned long app_virt_addr, - unsigned long data_size, - unsigned long *num_pages_ptr, - struct sep_lli_entry_t **lli_array_ptr, - struct page ***page_array_ptr) -{ - int error = 0; - /* the the page of the end address of the user space buffer */ - unsigned long end_page; - /* the page of the start address of the user space buffer */ - unsigned long start_page; - /* the range in pages */ - unsigned long num_pages; - struct page **page_array; - struct sep_lli_entry_t *lli_array; - unsigned long count; - int result; - - dbg("SEP Driver:--------> sep_lock_user_pages start\n"); - - /* set start and end pages and num pages */ - end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT; - start_page = app_virt_addr >> PAGE_SHIFT; - num_pages = end_page - start_page + 1; - - edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr); - edbg("SEP Driver: data_size is %lu\n", data_size); - edbg("SEP Driver: start_page is %lu\n", start_page); - edbg("SEP Driver: end_page is %lu\n", end_page); - edbg("SEP Driver: num_pages is %lu\n", num_pages); - - /* allocate array of pages structure pointers */ - page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC); - if (!page_array) { - edbg("SEP Driver: kmalloc for page_array failed\n"); - - error = -ENOMEM; - goto end_function; - } - - lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC); - if (!lli_array) { - edbg("SEP Driver: kmalloc for lli_array failed\n"); - - error = -ENOMEM; - goto end_function_with_error1; - } - - /* convert the application virtual address into a set of physical */ - down_read(¤t->mm->mmap_sem); - result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0); - up_read(¤t->mm->mmap_sem); - - /* check the number of pages locked - if not all then exit with error */ - if (result != num_pages) { - dbg("SEP Driver: not all pages locked by get_user_pages\n"); - - error = -ENOMEM; - goto end_function_with_error2; - } - - /* flush the cache */ - for (count = 0; count < num_pages; count++) - flush_dcache_page(page_array[count]); - - /* set the start address of the first page - app data may start not at - the beginning of the page */ - lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK)); - - /* check that not all the data is in the first page only */ - if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size) - lli_array[0].block_size = data_size; - else - lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK)); - - /* debug print */ - dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n", lli_array[0].physical_address, lli_array[0].block_size); - - /* go from the second page to the prev before last */ - for (count = 1; count < (num_pages - 1); count++) { - lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]); - lli_array[count].block_size = PAGE_SIZE; - - edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size); - } - - /* if more then 1 pages locked - then update for the last page size needed */ - if (num_pages > 1) { - /* update the address of the last page */ - lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]); - - /* set the size of the last page */ - lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK); - - if (lli_array[count].block_size == 0) { - dbg("app_virt_addr is %08lx\n", app_virt_addr); - dbg("data_size is %lu\n", data_size); - while (1); - } - edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n", - count, lli_array[count].physical_address, - count, lli_array[count].block_size); - } - - /* set output params */ - *lli_array_ptr = lli_array; - *num_pages_ptr = num_pages; - *page_array_ptr = page_array; - goto end_function; - -end_function_with_error2: - /* release the cache */ - for (count = 0; count < num_pages; count++) - page_cache_release(page_array[count]); - kfree(lli_array); -end_function_with_error1: - kfree(page_array); -end_function: - dbg("SEP Driver:<-------- sep_lock_user_pages end\n"); - return 0; -} - - -/* - this function calculates the size of data that can be inserted into the lli - table from this array the condition is that either the table is full - (all etnries are entered), or there are no more entries in the lli array -*/ -static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries) -{ - unsigned long table_data_size = 0; - unsigned long counter; - - /* calculate the data in the out lli table if till we fill the whole - table or till the data has ended */ - for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++) - table_data_size += lli_in_array_ptr[counter].block_size; - return table_data_size; -} - -/* - this functions builds ont lli table from the lli_array according to - the given size of data -*/ -static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr, struct sep_lli_entry_t *lli_table_ptr, unsigned long *num_processed_entries_ptr, unsigned long *num_table_entries_ptr, unsigned long table_data_size) -{ - unsigned long curr_table_data_size; - /* counter of lli array entry */ - unsigned long array_counter; - - dbg("SEP Driver:--------> sep_build_lli_table start\n"); - - /* init currrent table data size and lli array entry counter */ - curr_table_data_size = 0; - array_counter = 0; - *num_table_entries_ptr = 1; - - edbg("SEP Driver:table_data_size is %lu\n", table_data_size); - - /* fill the table till table size reaches the needed amount */ - while (curr_table_data_size < table_data_size) { - /* update the number of entries in table */ - (*num_table_entries_ptr)++; - - lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address; - lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size; - curr_table_data_size += lli_table_ptr->block_size; - - edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr); - edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - - /* check for overflow of the table data */ - if (curr_table_data_size > table_data_size) { - edbg("SEP Driver:curr_table_data_size > table_data_size\n"); - - /* update the size of block in the table */ - lli_table_ptr->block_size -= (curr_table_data_size - table_data_size); - - /* update the physical address in the lli array */ - lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size; - - /* update the block size left in the lli array */ - lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size); - } else - /* advance to the next entry in the lli_array */ - array_counter++; - - edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - - /* move to the next entry in table */ - lli_table_ptr++; - } - - /* set the info entry to default */ - lli_table_ptr->physical_address = 0xffffffff; - lli_table_ptr->block_size = 0; - - edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr); - edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - - /* set the output parameter */ - *num_processed_entries_ptr += array_counter; - - edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr); - dbg("SEP Driver:<-------- sep_build_lli_table end\n"); - return; -} - -/* - this function goes over the list of the print created tables and - prints all the data -*/ -static void sep_debug_print_lli_tables(struct sep_device *sep, struct sep_lli_entry_t *lli_table_ptr, unsigned long num_table_entries, unsigned long table_data_size) -{ - unsigned long table_count; - unsigned long entries_count; - - dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n"); - - table_count = 1; - while ((unsigned long) lli_table_ptr != 0xffffffff) { - edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size); - edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries); - - /* print entries of the table (without info entry) */ - for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) { - edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr); - edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size); - } - - /* point to the info entry */ - lli_table_ptr--; - - edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size); - edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address); - - - table_data_size = lli_table_ptr->block_size & 0xffffff; - num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff; - lli_table_ptr = (struct sep_lli_entry_t *) - (lli_table_ptr->physical_address); - - edbg("SEP Driver:phys table_data_size is %lu num_table_entries is %lu lli_table_ptr is%lu\n", table_data_size, num_table_entries, (unsigned long) lli_table_ptr); - - if ((unsigned long) lli_table_ptr != 0xffffffff) - lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_bus_to_virt(sep, (unsigned long) lli_table_ptr); - - table_count++; - } - dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n"); -} - - -/* - This function prepares only input DMA table for synhronic symmetric - operations (HASH) -*/ -static int sep_prepare_input_dma_table(struct sep_device *sep, - unsigned long app_virt_addr, - unsigned long data_size, - unsigned long block_size, - unsigned long *lli_table_ptr, - unsigned long *num_entries_ptr, - unsigned long *table_data_size_ptr, - bool isKernelVirtualAddress) -{ - /* pointer to the info entry of the table - the last entry */ - struct sep_lli_entry_t *info_entry_ptr; - /* array of pointers ot page */ - struct sep_lli_entry_t *lli_array_ptr; - /* points to the first entry to be processed in the lli_in_array */ - unsigned long current_entry; - /* num entries in the virtual buffer */ - unsigned long sep_lli_entries; - /* lli table pointer */ - struct sep_lli_entry_t *in_lli_table_ptr; - /* the total data in one table */ - unsigned long table_data_size; - /* number of entries in lli table */ - unsigned long num_entries_in_table; - /* next table address */ - void *lli_table_alloc_addr; - unsigned long result; - - dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n"); - - edbg("SEP Driver:data_size is %lu\n", data_size); - edbg("SEP Driver:block_size is %lu\n", block_size); - - /* initialize the pages pointers */ - sep->in_page_array = 0; - sep->in_num_pages = 0; - - if (data_size == 0) { - /* special case - created 2 entries table with zero data */ - in_lli_table_ptr = (struct sep_lli_entry_t *) (sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES); - /* FIXME: Should the entry below not be for _bus */ - in_lli_table_ptr->physical_address = (unsigned long)sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES; - in_lli_table_ptr->block_size = 0; - - in_lli_table_ptr++; - in_lli_table_ptr->physical_address = 0xFFFFFFFF; - in_lli_table_ptr->block_size = 0; - - *lli_table_ptr = sep->shared_bus + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES; - *num_entries_ptr = 2; - *table_data_size_ptr = 0; - - goto end_function; - } - - /* check if the pages are in Kernel Virtual Address layout */ - if (isKernelVirtualAddress == true) - /* lock the pages of the kernel buffer and translate them to pages */ - result = sep_lock_kernel_pages(sep, app_virt_addr, data_size, &sep->in_num_pages, &lli_array_ptr, &sep->in_page_array); - else - /* lock the pages of the user buffer and translate them to pages */ - result = sep_lock_user_pages(sep, app_virt_addr, data_size, &sep->in_num_pages, &lli_array_ptr, &sep->in_page_array); - - if (result) - return result; - - edbg("SEP Driver:output sep->in_num_pages is %lu\n", sep->in_num_pages); - - current_entry = 0; - info_entry_ptr = 0; - sep_lli_entries = sep->in_num_pages; - - /* initiate to point after the message area */ - lli_table_alloc_addr = sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES; - - /* loop till all the entries in in array are not processed */ - while (current_entry < sep_lli_entries) { - /* set the new input and output tables */ - in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* calculate the maximum size of data for input table */ - table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry)); - - /* now calculate the table size so that it will be module block size */ - table_data_size = (table_data_size / block_size) * block_size; - - edbg("SEP Driver:output table_data_size is %lu\n", table_data_size); - - /* construct input lli table */ - sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, ¤t_entry, &num_entries_in_table, table_data_size); - - if (info_entry_ptr == 0) { - /* set the output parameters to physical addresses */ - *lli_table_ptr = sep_shared_virt_to_bus(sep, in_lli_table_ptr); - *num_entries_ptr = num_entries_in_table; - *table_data_size_ptr = table_data_size; - - edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr); - } else { - /* update the info entry of the previous in table */ - info_entry_ptr->physical_address = sep_shared_virt_to_bus(sep, in_lli_table_ptr); - info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size); - } - - /* save the pointer to the info entry of the current tables */ - info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1; - } - - /* print input tables */ - sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *) - sep_shared_bus_to_virt(sep, *lli_table_ptr), *num_entries_ptr, *table_data_size_ptr); - - /* the array of the pages */ - kfree(lli_array_ptr); -end_function: - dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n"); - return 0; - -} - -/* - This function creates the input and output dma tables for - symmetric operations (AES/DES) according to the block size from LLI arays -*/ -static int sep_construct_dma_tables_from_lli(struct sep_device *sep, - struct sep_lli_entry_t *lli_in_array, - unsigned long sep_in_lli_entries, - struct sep_lli_entry_t *lli_out_array, - unsigned long sep_out_lli_entries, - unsigned long block_size, unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr) -{ - /* points to the area where next lli table can be allocated: keep void * - as there is pointer scaling to fix otherwise */ - void *lli_table_alloc_addr; - /* input lli table */ - struct sep_lli_entry_t *in_lli_table_ptr; - /* output lli table */ - struct sep_lli_entry_t *out_lli_table_ptr; - /* pointer to the info entry of the table - the last entry */ - struct sep_lli_entry_t *info_in_entry_ptr; - /* pointer to the info entry of the table - the last entry */ - struct sep_lli_entry_t *info_out_entry_ptr; - /* points to the first entry to be processed in the lli_in_array */ - unsigned long current_in_entry; - /* points to the first entry to be processed in the lli_out_array */ - unsigned long current_out_entry; - /* max size of the input table */ - unsigned long in_table_data_size; - /* max size of the output table */ - unsigned long out_table_data_size; - /* flag te signifies if this is the first tables build from the arrays */ - unsigned long first_table_flag; - /* the data size that should be in table */ - unsigned long table_data_size; - /* number of etnries in the input table */ - unsigned long num_entries_in_table; - /* number of etnries in the output table */ - unsigned long num_entries_out_table; - - dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n"); - - /* initiate to pint after the message area */ - lli_table_alloc_addr = sep->shared_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES; - - current_in_entry = 0; - current_out_entry = 0; - first_table_flag = 1; - info_in_entry_ptr = 0; - info_out_entry_ptr = 0; - - /* loop till all the entries in in array are not processed */ - while (current_in_entry < sep_in_lli_entries) { - /* set the new input and output tables */ - in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* set the first output tables */ - out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr; - - lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP; - - /* calculate the maximum size of data for input table */ - in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry)); - - /* calculate the maximum size of data for output table */ - out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry)); - - edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size); - edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size); - - /* check where the data is smallest */ - table_data_size = in_table_data_size; - if (table_data_size > out_table_data_size) - table_data_size = out_table_data_size; - - /* now calculate the table size so that it will be module block size */ - table_data_size = (table_data_size / block_size) * block_size; - - dbg("SEP Driver:table_data_size is %lu\n", table_data_size); - - /* construct input lli table */ - sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, ¤t_in_entry, &num_entries_in_table, table_data_size); - - /* construct output lli table */ - sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, ¤t_out_entry, &num_entries_out_table, table_data_size); - - /* if info entry is null - this is the first table built */ - if (info_in_entry_ptr == 0) { - /* set the output parameters to physical addresses */ - *lli_table_in_ptr = sep_shared_virt_to_bus(sep, in_lli_table_ptr); - *in_num_entries_ptr = num_entries_in_table; - *lli_table_out_ptr = sep_shared_virt_to_bus(sep, out_lli_table_ptr); - *out_num_entries_ptr = num_entries_out_table; - *table_data_size_ptr = table_data_size; - - edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr); - edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr); - } else { - /* update the info entry of the previous in table */ - info_in_entry_ptr->physical_address = sep_shared_virt_to_bus(sep, in_lli_table_ptr); - info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size); - - /* update the info entry of the previous in table */ - info_out_entry_ptr->physical_address = sep_shared_virt_to_bus(sep, out_lli_table_ptr); - info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size); - } - - /* save the pointer to the info entry of the current tables */ - info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1; - info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1; - - edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table); - edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr); - edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr); - } - - /* print input tables */ - sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *) - sep_shared_bus_to_virt(sep, *lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr); - /* print output tables */ - sep_debug_print_lli_tables(sep, (struct sep_lli_entry_t *) - sep_shared_bus_to_virt(sep, *lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr); - dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n"); - return 0; -} - - -/* - This function builds input and output DMA tables for synhronic - symmetric operations (AES, DES). It also checks that each table - is of the modular block size -*/ -static int sep_prepare_input_output_dma_table(struct sep_device *sep, - unsigned long app_virt_in_addr, - unsigned long app_virt_out_addr, - unsigned long data_size, - unsigned long block_size, - unsigned long *lli_table_in_ptr, unsigned long *lli_table_out_ptr, unsigned long *in_num_entries_ptr, unsigned long *out_num_entries_ptr, unsigned long *table_data_size_ptr, bool isKernelVirtualAddress) -{ - /* array of pointers of page */ - struct sep_lli_entry_t *lli_in_array; - /* array of pointers of page */ - struct sep_lli_entry_t *lli_out_array; - int result = 0; - - dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n"); - - /* initialize the pages pointers */ - sep->in_page_array = 0; - sep->out_page_array = 0; - - /* check if the pages are in Kernel Virtual Address layout */ - if (isKernelVirtualAddress == true) { - /* lock the pages of the kernel buffer and translate them to pages */ - result = sep_lock_kernel_pages(sep, app_virt_in_addr, data_size, &sep->in_num_pages, &lli_in_array, &sep->in_page_array); - if (result) { - edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n"); - goto end_function; - } - } else { - /* lock the pages of the user buffer and translate them to pages */ - result = sep_lock_user_pages(sep, app_virt_in_addr, data_size, &sep->in_num_pages, &lli_in_array, &sep->in_page_array); - if (result) { - edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n"); - goto end_function; - } - } - - if (isKernelVirtualAddress == true) { - result = sep_lock_kernel_pages(sep, app_virt_out_addr, data_size, &sep->out_num_pages, &lli_out_array, &sep->out_page_array); - if (result) { - edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n"); - goto end_function_with_error1; - } - } else { - result = sep_lock_user_pages(sep, app_virt_out_addr, data_size, &sep->out_num_pages, &lli_out_array, &sep->out_page_array); - if (result) { - edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n"); - goto end_function_with_error1; - } - } - edbg("sep->in_num_pages is %lu\n", sep->in_num_pages); - edbg("sep->out_num_pages is %lu\n", sep->out_num_pages); - edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP); - - - /* call the fucntion that creates table from the lli arrays */ - result = sep_construct_dma_tables_from_lli(sep, lli_in_array, sep->in_num_pages, lli_out_array, sep->out_num_pages, block_size, lli_table_in_ptr, lli_table_out_ptr, in_num_entries_ptr, out_num_entries_ptr, table_data_size_ptr); - if (result) { - edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n"); - goto end_function_with_error2; - } - - /* fall through - free the lli entry arrays */ - dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr); - dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr); - dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr); -end_function_with_error2: - kfree(lli_out_array); -end_function_with_error1: - kfree(lli_in_array); -end_function: - dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result); - return result; - -} - -/* - this function handles tha request for creation of the DMA table - for the synchronic symmetric operations (AES,DES) -*/ -static int sep_create_sync_dma_tables_handler(struct sep_device *sep, - unsigned long arg) -{ - int error; - /* command arguments */ - struct sep_driver_build_sync_table_t command_args; - - dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n"); - - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - edbg("app_in_address is %08lx\n", command_args.app_in_address); - edbg("app_out_address is %08lx\n", command_args.app_out_address); - edbg("data_size is %lu\n", command_args.data_in_size); - edbg("block_size is %lu\n", command_args.block_size); - - /* check if we need to build only input table or input/output */ - if (command_args.app_out_address) - /* prepare input and output tables */ - error = sep_prepare_input_output_dma_table(sep, - command_args.app_in_address, - command_args.app_out_address, - command_args.data_in_size, - command_args.block_size, - &command_args.in_table_address, - &command_args.out_table_address, &command_args.in_table_num_entries, &command_args.out_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress); - else - /* prepare input tables */ - error = sep_prepare_input_dma_table(sep, - command_args.app_in_address, - command_args.data_in_size, command_args.block_size, &command_args.in_table_address, &command_args.in_table_num_entries, &command_args.table_data_size, command_args.isKernelVirtualAddress); - - if (error) - goto end_function; - /* copy to user */ - if (copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t))) - error = -EFAULT; -end_function: - dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n"); - return error; -} - -/* - this function handles the request for freeing dma table for synhronic actions -*/ -static int sep_free_dma_table_data_handler(struct sep_device *sep) -{ - dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n"); - - /* free input pages array */ - sep_free_dma_pages(sep->in_page_array, sep->in_num_pages, 0); - - /* free output pages array if needed */ - if (sep->out_page_array) - sep_free_dma_pages(sep->out_page_array, sep->out_num_pages, 1); - - /* reset all the values */ - sep->in_page_array = 0; - sep->out_page_array = 0; - sep->in_num_pages = 0; - sep->out_num_pages = 0; - dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n"); - return 0; -} - -/* - this function find a space for the new flow dma table -*/ -static int sep_find_free_flow_dma_table_space(struct sep_device *sep, - unsigned long **table_address_ptr) -{ - int error = 0; - /* pointer to the id field of the flow dma table */ - unsigned long *start_table_ptr; - /* Do not make start_addr unsigned long * unless fixing the offset - computations ! */ - void *flow_dma_area_start_addr; - unsigned long *flow_dma_area_end_addr; - /* maximum table size in words */ - unsigned long table_size_in_words; - - /* find the start address of the flow DMA table area */ - flow_dma_area_start_addr = sep->shared_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES; - - /* set end address of the flow table area */ - flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES; - - /* set table size in words */ - table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2; - - /* set the pointer to the start address of DMA area */ - start_table_ptr = flow_dma_area_start_addr; - - /* find the space for the next table */ - while (((*start_table_ptr & 0x7FFFFFFF) != 0) && start_table_ptr < flow_dma_area_end_addr) - start_table_ptr += table_size_in_words; - - /* check if we reached the end of floa tables area */ - if (start_table_ptr >= flow_dma_area_end_addr) - error = -1; - else - *table_address_ptr = start_table_ptr; - - return error; -} - -/* - This function creates one DMA table for flow and returns its data, - and pointer to its info entry -*/ -static int sep_prepare_one_flow_dma_table(struct sep_device *sep, - unsigned long virt_buff_addr, - unsigned long virt_buff_size, - struct sep_lli_entry_t *table_data, - struct sep_lli_entry_t **info_entry_ptr, - struct sep_flow_context_t *flow_data_ptr, - bool isKernelVirtualAddress) -{ - int error; - /* the range in pages */ - unsigned long lli_array_size; - struct sep_lli_entry_t *lli_array; - struct sep_lli_entry_t *flow_dma_table_entry_ptr; - unsigned long *start_dma_table_ptr; - /* total table data counter */ - unsigned long dma_table_data_count; - /* pointer that will keep the pointer to the pages of the virtual buffer */ - struct page **page_array_ptr; - unsigned long entry_count; - - /* find the space for the new table */ - error = sep_find_free_flow_dma_table_space(sep, &start_dma_table_ptr); - if (error) - goto end_function; - - /* check if the pages are in Kernel Virtual Address layout */ - if (isKernelVirtualAddress == true) - /* lock kernel buffer in the memory */ - error = sep_lock_kernel_pages(sep, virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr); - else - /* lock user buffer in the memory */ - error = sep_lock_user_pages(sep, virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr); - - if (error) - goto end_function; - - /* set the pointer to page array at the beginning of table - this table is - now considered taken */ - *start_dma_table_ptr = lli_array_size; - - /* point to the place of the pages pointers of the table */ - start_dma_table_ptr++; - - /* set the pages pointer */ - *start_dma_table_ptr = (unsigned long) page_array_ptr; - - /* set the pointer to the first entry */ - flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr); - - /* now create the entries for table */ - for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) { - flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address; - - flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size; - - /* set the total data of a table */ - dma_table_data_count += lli_array[entry_count].block_size; - - flow_dma_table_entry_ptr++; - } - - /* set the physical address */ - table_data->physical_address = virt_to_phys(start_dma_table_ptr); - - /* set the num_entries and total data size */ - table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count); - - /* set the info entry */ - flow_dma_table_entry_ptr->physical_address = 0xffffffff; - flow_dma_table_entry_ptr->block_size = 0; - - /* set the pointer to info entry */ - *info_entry_ptr = flow_dma_table_entry_ptr; - - /* the array of the lli entries */ - kfree(lli_array); -end_function: - return error; -} - - - -/* - This function creates a list of tables for flow and returns the data for - the first and last tables of the list -*/ -static int sep_prepare_flow_dma_tables(struct sep_device *sep, - unsigned long num_virtual_buffers, - unsigned long first_buff_addr, struct sep_flow_context_t *flow_data_ptr, struct sep_lli_entry_t *first_table_data_ptr, struct sep_lli_entry_t *last_table_data_ptr, bool isKernelVirtualAddress) -{ - int error; - unsigned long virt_buff_addr; - unsigned long virt_buff_size; - struct sep_lli_entry_t table_data; - struct sep_lli_entry_t *info_entry_ptr; - struct sep_lli_entry_t *prev_info_entry_ptr; - unsigned long i; - - /* init vars */ - error = 0; - prev_info_entry_ptr = 0; - - /* init the first table to default */ - table_data.physical_address = 0xffffffff; - first_table_data_ptr->physical_address = 0xffffffff; - table_data.block_size = 0; - - for (i = 0; i < num_virtual_buffers; i++) { - /* get the virtual buffer address */ - error = get_user(virt_buff_addr, &first_buff_addr); - if (error) - goto end_function; - - /* get the virtual buffer size */ - first_buff_addr++; - error = get_user(virt_buff_size, &first_buff_addr); - if (error) - goto end_function; - - /* advance the address to point to the next pair of address|size */ - first_buff_addr++; - - /* now prepare the one flow LLI table from the data */ - error = sep_prepare_one_flow_dma_table(sep, virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress); - if (error) - goto end_function; - - if (i == 0) { - /* if this is the first table - save it to return to the user - application */ - *first_table_data_ptr = table_data; - - /* set the pointer to info entry */ - prev_info_entry_ptr = info_entry_ptr; - } else { - /* not first table - the previous table info entry should - be updated */ - prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size); - - /* set the pointer to info entry */ - prev_info_entry_ptr = info_entry_ptr; - } - } - - /* set the last table data */ - *last_table_data_ptr = table_data; -end_function: - return error; -} - -/* - this function goes over all the flow tables connected to the given - table and deallocate them -*/ -static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr) -{ - /* id pointer */ - unsigned long *table_ptr; - /* end address of the flow dma area */ - unsigned long num_entries; - unsigned long num_pages; - struct page **pages_ptr; - /* maximum table size in words */ - struct sep_lli_entry_t *info_entry_ptr; - - /* set the pointer to the first table */ - table_ptr = (unsigned long *) first_table_ptr->physical_address; - - /* set the num of entries */ - num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) - & SEP_NUM_ENTRIES_MASK; - - /* go over all the connected tables */ - while (*table_ptr != 0xffffffff) { - /* get number of pages */ - num_pages = *(table_ptr - 2); - - /* get the pointer to the pages */ - pages_ptr = (struct page **) (*(table_ptr - 1)); - - /* free the pages */ - sep_free_dma_pages(pages_ptr, num_pages, 1); - - /* goto to the info entry */ - info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1); - - table_ptr = (unsigned long *) info_entry_ptr->physical_address; - num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK; - } - - return; -} - -/** - * sep_find_flow_context - find a flow - * @sep: the SEP we are working with - * @flow_id: flow identifier - * - * Returns a pointer the matching flow, or NULL if the flow does not - * exist. - */ - -static struct sep_flow_context_t *sep_find_flow_context(struct sep_device *sep, - unsigned long flow_id) -{ - int count; - /* - * always search for flow with id default first - in case we - * already started working on the flow there can be no situation - * when 2 flows are with default flag - */ - for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) { - if (sep->flows[count].flow_id == flow_id) - return &sep->flows[count]; - } - return NULL; -} - - -/* - this function handles the request to create the DMA tables for flow -*/ -static int sep_create_flow_dma_tables_handler(struct sep_device *sep, - unsigned long arg) -{ - int error = -ENOENT; - struct sep_driver_build_flow_table_t command_args; - /* first table - output */ - struct sep_lli_entry_t first_table_data; - /* dma table data */ - struct sep_lli_entry_t last_table_data; - /* pointer to the info entry of the previuos DMA table */ - struct sep_lli_entry_t *prev_info_entry_ptr; - /* pointer to the flow data strucutre */ - struct sep_flow_context_t *flow_context_ptr; - - dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n"); - - /* init variables */ - prev_info_entry_ptr = 0; - first_table_data.physical_address = 0xffffffff; - - /* find the free structure for flow data */ - error = -EINVAL; - flow_context_ptr = sep_find_flow_context(sep, SEP_FREE_FLOW_ID); - if (flow_context_ptr == NULL) - goto end_function; - - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - /* create flow tables */ - error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress); - if (error) - goto end_function_with_error; - - /* check if flow is static */ - if (!command_args.flow_type) - /* point the info entry of the last to the info entry of the first */ - last_table_data = first_table_data; - - /* set output params */ - command_args.first_table_addr = first_table_data.physical_address; - command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK); - command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK); - - /* send the parameters to user application */ - error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t)); - if (error) { - error = -EFAULT; - goto end_function_with_error; - } - - /* all the flow created - update the flow entry with temp id */ - flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID; - - /* set the processing tables data in the context */ - if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG) - flow_context_ptr->input_tables_in_process = first_table_data; - else - flow_context_ptr->output_tables_in_process = first_table_data; - - goto end_function; - -end_function_with_error: - /* free the allocated tables */ - sep_deallocated_flow_tables(&first_table_data); -end_function: - dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n"); - return error; -} - -/* - this function handles add tables to flow -*/ -static int sep_add_flow_tables_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - unsigned long num_entries; - struct sep_driver_add_flow_table_t command_args; - struct sep_flow_context_t *flow_context_ptr; - /* first dma table data */ - struct sep_lli_entry_t first_table_data; - /* last dma table data */ - struct sep_lli_entry_t last_table_data; - /* pointer to the info entry of the current DMA table */ - struct sep_lli_entry_t *info_entry_ptr; - - dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n"); - - /* get input parameters */ - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - /* find the flow structure for the flow id */ - flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id); - if (flow_context_ptr == NULL) - goto end_function; - - /* prepare the flow dma tables */ - error = sep_prepare_flow_dma_tables(sep, command_args.num_virtual_buffers, command_args.virt_buff_data_addr, flow_context_ptr, &first_table_data, &last_table_data, command_args.isKernelVirtualAddress); - if (error) - goto end_function_with_error; - - /* now check if there is already an existing add table for this flow */ - if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) { - /* this buffer was for input buffers */ - if (flow_context_ptr->input_tables_flag) { - /* add table already exists - add the new tables to the end - of the previous */ - num_entries = (flow_context_ptr->last_input_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK; - - info_entry_ptr = (struct sep_lli_entry_t *) - (flow_context_ptr->last_input_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1))); - - /* connect to list of tables */ - *info_entry_ptr = first_table_data; - - /* set the first table data */ - first_table_data = flow_context_ptr->first_input_table; - } else { - /* set the input flag */ - flow_context_ptr->input_tables_flag = 1; - - /* set the first table data */ - flow_context_ptr->first_input_table = first_table_data; - } - /* set the last table data */ - flow_context_ptr->last_input_table = last_table_data; - } else { /* this is output tables */ - - /* this buffer was for input buffers */ - if (flow_context_ptr->output_tables_flag) { - /* add table already exists - add the new tables to - the end of the previous */ - num_entries = (flow_context_ptr->last_output_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK; - - info_entry_ptr = (struct sep_lli_entry_t *) - (flow_context_ptr->last_output_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1))); - - /* connect to list of tables */ - *info_entry_ptr = first_table_data; - - /* set the first table data */ - first_table_data = flow_context_ptr->first_output_table; - } else { - /* set the input flag */ - flow_context_ptr->output_tables_flag = 1; - - /* set the first table data */ - flow_context_ptr->first_output_table = first_table_data; - } - /* set the last table data */ - flow_context_ptr->last_output_table = last_table_data; - } - - /* set output params */ - command_args.first_table_addr = first_table_data.physical_address; - command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK); - command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK); - - /* send the parameters to user application */ - error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t)); - if (error) - error = -EFAULT; -end_function_with_error: - /* free the allocated tables */ - sep_deallocated_flow_tables(&first_table_data); -end_function: - dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n"); - return error; -} - -/* - this function add the flow add message to the specific flow -*/ -static int sep_add_flow_tables_message_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - struct sep_driver_add_message_t command_args; - struct sep_flow_context_t *flow_context_ptr; - - dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n"); - - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - /* check input */ - if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) { - error = -ENOMEM; - goto end_function; - } - - /* find the flow context */ - flow_context_ptr = sep_find_flow_context(sep, command_args.flow_id); - if (flow_context_ptr == NULL) - goto end_function; - - /* copy the message into context */ - flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes; - error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes); - if (error) - error = -EFAULT; -end_function: - dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n"); - return error; -} - - -/* - this function returns the bus and virtual addresses of the static pool -*/ -static int sep_get_static_pool_addr_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - struct sep_driver_static_pool_addr_t command_args; - - dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n"); - - /*prepare the output parameters in the struct */ - command_args.physical_static_address = sep->shared_bus + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES; - command_args.virtual_static_address = (unsigned long)sep->shared_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES; - - edbg("SEP Driver:bus_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address); - - /* send the parameters to user application */ - error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t)); - if (error) - error = -EFAULT; - dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n"); - return error; -} - -/* - this address gets the offset of the physical address from the start - of the mapped area -*/ -static int sep_get_physical_mapped_offset_handler(struct sep_device *sep, unsigned long arg) -{ - int error; - struct sep_driver_get_mapped_offset_t command_args; - - dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n"); - - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - - if (command_args.physical_address < sep->shared_bus) { - error = -EINVAL; - goto end_function; - } - - /*prepare the output parameters in the struct */ - command_args.offset = command_args.physical_address - sep->shared_bus; - - edbg("SEP Driver:bus_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset); - - /* send the parameters to user application */ - error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t)); - if (error) - error = -EFAULT; -end_function: - dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n"); - return error; -} - - -/* - ? -*/ -static int sep_start_handler(struct sep_device *sep) -{ - unsigned long reg_val; - unsigned long error = 0; - - dbg("SEP Driver:--------> sep_start_handler start\n"); - - /* wait in polling for message from SEP */ - do - reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); - while (!reg_val); - - /* check the value */ - if (reg_val == 0x1) - /* fatal error - read error status from GPRO */ - error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR); - dbg("SEP Driver:<-------- sep_start_handler end\n"); - return error; -} - -/* - this function handles the request for SEP initialization -*/ -static int sep_init_handler(struct sep_device *sep, unsigned long arg) -{ - unsigned long message_word; - unsigned long *message_ptr; - struct sep_driver_init_t command_args; - unsigned long counter; - unsigned long error; - unsigned long reg_val; - - dbg("SEP Driver:--------> sep_init_handler start\n"); - error = 0; - - error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t)); - if (error) { - error = -EFAULT; - goto end_function; - } - dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user\n"); - - /* PATCH - configure the DMA to single -burst instead of multi-burst */ - /*sep_configure_dma_burst(); */ - - dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n"); - - message_ptr = (unsigned long *) command_args.message_addr; - - /* set the base address of the SRAM */ - sep_write_reg(sep, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS); - - for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) { - get_user(message_word, message_ptr); - /* write data to SRAM */ - sep_write_reg(sep, HW_SRAM_DATA_REG_ADDR, message_word); - edbg("SEP Driver:message_word is %lu\n", message_word); - /* wait for write complete */ - sep_wait_sram_write(sep); - } - dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n"); - /* signal SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1); - - do - reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR); - while (!(reg_val & 0xFFFFFFFD)); - - dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n"); - - /* check the value */ - if (reg_val == 0x1) { - edbg("SEP Driver:init failed\n"); - - error = sep_read_reg(sep, 0x8060); - edbg("SEP Driver:sw monitor is %lu\n", error); - - /* fatal error - read erro status from GPRO */ - error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR); - edbg("SEP Driver:error is %lu\n", error); - } -end_function: - dbg("SEP Driver:<-------- sep_init_handler end\n"); - return error; - -} - -/* - this function handles the request cache and resident reallocation -*/ -static int sep_realloc_cache_resident_handler(struct sep_device *sep, - unsigned long arg) -{ - struct sep_driver_realloc_cache_resident_t command_args; - int error; - - /* copy cache and resident to the their intended locations */ - error = sep_load_firmware(sep); - if (error) - return error; - - command_args.new_base_addr = sep->shared_bus; - - /* find the new base address according to the lowest address between - cache, resident and shared area */ - if (sep->resident_bus < command_args.new_base_addr) - command_args.new_base_addr = sep->resident_bus; - if (sep->rar_bus < command_args.new_base_addr) - command_args.new_base_addr = sep->rar_bus; - - /* set the return parameters */ - command_args.new_cache_addr = sep->rar_bus; - command_args.new_resident_addr = sep->resident_bus; - - /* set the new shared area */ - command_args.new_shared_area_addr = sep->shared_bus; - - edbg("SEP Driver:command_args.new_shared_addr is %08llx\n", command_args.new_shared_area_addr); - edbg("SEP Driver:command_args.new_base_addr is %08llx\n", command_args.new_base_addr); - edbg("SEP Driver:command_args.new_resident_addr is %08llx\n", command_args.new_resident_addr); - edbg("SEP Driver:command_args.new_rar_addr is %08llx\n", command_args.new_cache_addr); - - /* return to user */ - if (copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_realloc_cache_resident_t))) - return -EFAULT; - return 0; -} - -/** - * sep_get_time_handler - time request from user space - * @sep: sep we are to set the time for - * @arg: pointer to user space arg buffer - * - * This function reports back the time and the address in the SEP - * shared buffer at which it has been placed. (Do we really need this!!!) - */ - -static int sep_get_time_handler(struct sep_device *sep, unsigned long arg) -{ - struct sep_driver_get_time_t command_args; - - mutex_lock(&sep_mutex); - command_args.time_value = sep_set_time(sep); - command_args.time_physical_address = (unsigned long)sep_time_address(sep); - mutex_unlock(&sep_mutex); - if (copy_to_user((void __user *)arg, - &command_args, sizeof(struct sep_driver_get_time_t))) - return -EFAULT; - return 0; - -} - -/* - This API handles the end transaction request -*/ -static int sep_end_transaction_handler(struct sep_device *sep, unsigned long arg) -{ - dbg("SEP Driver:--------> sep_end_transaction_handler start\n"); - -#if 0 /*!SEP_DRIVER_POLLING_MODE */ - /* close IMR */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF); - - /* release IRQ line */ - free_irq(SEP_DIRVER_IRQ_NUM, sep); - - /* lock the sep mutex */ - mutex_unlock(&sep_mutex); -#endif - - dbg("SEP Driver:<-------- sep_end_transaction_handler end\n"); - - return 0; -} - - -/** - * sep_set_flow_id_handler - handle flow setting - * @sep: the SEP we are configuring - * @flow_id: the flow we are setting - * - * This function handler the set flow id command - */ -static int sep_set_flow_id_handler(struct sep_device *sep, - unsigned long flow_id) -{ - int error = 0; - struct sep_flow_context_t *flow_data_ptr; - - /* find the flow data structure that was just used for creating new flow - - its id should be default */ - - mutex_lock(&sep_mutex); - flow_data_ptr = sep_find_flow_context(sep, SEP_TEMP_FLOW_ID); - if (flow_data_ptr) - flow_data_ptr->flow_id = flow_id; /* set flow id */ - else - error = -EINVAL; - mutex_unlock(&sep_mutex); - return error; -} - -static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - int error = 0; - struct sep_device *sep = filp->private_data; - - dbg("------------>SEP Driver: ioctl start\n"); - - edbg("SEP Driver: cmd is %x\n", cmd); - - switch (cmd) { - case SEP_IOCSENDSEPCOMMAND: - /* send command to SEP */ - sep_send_command_handler(sep); - edbg("SEP Driver: after sep_send_command_handler\n"); - break; - case SEP_IOCSENDSEPRPLYCOMMAND: - /* send reply command to SEP */ - sep_send_reply_command_handler(sep); - break; - case SEP_IOCALLOCDATAPOLL: - /* allocate data pool */ - error = sep_allocate_data_pool_memory_handler(sep, arg); - break; - case SEP_IOCWRITEDATAPOLL: - /* write data into memory pool */ - error = sep_write_into_data_pool_handler(sep, arg); - break; - case SEP_IOCREADDATAPOLL: - /* read data from data pool into application memory */ - error = sep_read_from_data_pool_handler(sep, arg); - break; - case SEP_IOCCREATESYMDMATABLE: - /* create dma table for synhronic operation */ - error = sep_create_sync_dma_tables_handler(sep, arg); - break; - case SEP_IOCCREATEFLOWDMATABLE: - /* create flow dma tables */ - error = sep_create_flow_dma_tables_handler(sep, arg); - break; - case SEP_IOCFREEDMATABLEDATA: - /* free the pages */ - error = sep_free_dma_table_data_handler(sep); - break; - case SEP_IOCSETFLOWID: - /* set flow id */ - error = sep_set_flow_id_handler(sep, (unsigned long)arg); - break; - case SEP_IOCADDFLOWTABLE: - /* add tables to the dynamic flow */ - error = sep_add_flow_tables_handler(sep, arg); - break; - case SEP_IOCADDFLOWMESSAGE: - /* add message of add tables to flow */ - error = sep_add_flow_tables_message_handler(sep, arg); - break; - case SEP_IOCSEPSTART: - /* start command to sep */ - error = sep_start_handler(sep); - break; - case SEP_IOCSEPINIT: - /* init command to sep */ - error = sep_init_handler(sep, arg); - break; - case SEP_IOCGETSTATICPOOLADDR: - /* get the physical and virtual addresses of the static pool */ - error = sep_get_static_pool_addr_handler(sep, arg); - break; - case SEP_IOCENDTRANSACTION: - error = sep_end_transaction_handler(sep, arg); - break; - case SEP_IOCREALLOCCACHERES: - error = sep_realloc_cache_resident_handler(sep, arg); - break; - case SEP_IOCGETMAPPEDADDROFFSET: - error = sep_get_physical_mapped_offset_handler(sep, arg); - break; - case SEP_IOCGETIME: - error = sep_get_time_handler(sep, arg); - break; - default: - error = -ENOTTY; - break; - } - dbg("SEP Driver:<-------- ioctl end\n"); - return error; -} - - - -#if !SEP_DRIVER_POLLING_MODE - -/* handler for flow done interrupt */ - -static void sep_flow_done_handler(struct work_struct *work) -{ - struct sep_flow_context_t *flow_data_ptr; - - /* obtain the mutex */ - mutex_lock(&sep_mutex); - - /* get the pointer to context */ - flow_data_ptr = (struct sep_flow_context_t *) work; - - /* free all the current input tables in sep */ - sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process); - - /* free all the current tables output tables in SEP (if needed) */ - if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff) - sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process); - - /* check if we have additional tables to be sent to SEP only input - flag may be checked */ - if (flow_data_ptr->input_tables_flag) { - /* copy the message to the shared RAM and signal SEP */ - memcpy((void *) flow_data_ptr->message, (void *) sep->shared_addr, flow_data_ptr->message_size_in_bytes); - - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2); - } - mutex_unlock(&sep_mutex); -} -/* - interrupt handler function -*/ -static irqreturn_t sep_inthandler(int irq, void *dev_id) -{ - irqreturn_t int_error; - unsigned long reg_val; - unsigned long flow_id; - struct sep_flow_context_t *flow_context_ptr; - struct sep_device *sep = dev_id; - - int_error = IRQ_HANDLED; - - /* read the IRR register to check if this is SEP interrupt */ - reg_val = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR); - edbg("SEP Interrupt - reg is %08lx\n", reg_val); - - /* check if this is the flow interrupt */ - if (0 /*reg_val & (0x1 << 11) */ ) { - /* read GPRO to find out the which flow is done */ - flow_id = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR); - - /* find the contex of the flow */ - flow_context_ptr = sep_find_flow_context(sep, flow_id >> 28); - if (flow_context_ptr == NULL) - goto end_function_with_error; - - /* queue the work */ - INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler); - queue_work(sep->flow_wq, &flow_context_ptr->flow_wq); - - } else { - /* check if this is reply interrupt from SEP */ - if (reg_val & (0x1 << 13)) { - /* update the counter of reply messages */ - sep->reply_ct++; - /* wake up the waiting process */ - wake_up(&sep_event); - } else { - int_error = IRQ_NONE; - goto end_function; - } - } -end_function_with_error: - /* clear the interrupt */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, reg_val); -end_function: - return int_error; -} - -#endif - - - -#if 0 - -static void sep_wait_busy(struct sep_device *sep) -{ - u32 reg; - - do { - reg = sep_read_reg(sep, HW_HOST_SEP_BUSY_REG_ADDR); - } while (reg); -} - -/* - PATCH for configuring the DMA to single burst instead of multi-burst -*/ -static void sep_configure_dma_burst(struct sep_device *sep) -{ -#define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL - - dbg("SEP Driver:<-------- sep_configure_dma_burst start \n"); - - /* request access to registers from SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2); - - dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n"); - - sep_wait_busy(sep); - - dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n"); - - /* set the DMA burst register to single burst */ - sep_write_reg(sep, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL); - - /* release the sep busy */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL); - sep_wait_busy(sep); - - dbg("SEP Driver:<-------- sep_configure_dma_burst done \n"); - -} - -#endif - -/* - Function that is activated on the successful probe of the SEP device -*/ -static int __devinit sep_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int error = 0; - struct sep_device *sep; - int counter; - int size; /* size of memory for allocation */ - - edbg("Sep pci probe starting\n"); - if (sep_dev != NULL) { - dev_warn(&pdev->dev, "only one SEP supported.\n"); - return -EBUSY; - } - - /* enable the device */ - error = pci_enable_device(pdev); - if (error) { - edbg("error enabling pci device\n"); - goto end_function; - } - - /* set the pci dev pointer */ - sep_dev = &sep_instance; - sep = &sep_instance; - - edbg("sep->shared_addr = %p\n", sep->shared_addr); - /* transaction counter that coordinates the transactions between SEP - and HOST */ - sep->send_ct = 0; - /* counter for the messages from sep */ - sep->reply_ct = 0; - /* counter for the number of bytes allocated in the pool - for the current transaction */ - sep->data_pool_bytes_allocated = 0; - - /* calculate the total size for allocation */ - size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + - SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES; - - /* allocate the shared area */ - if (sep_map_and_alloc_shared_area(sep, size)) { - error = -ENOMEM; - /* allocation failed */ - goto end_function_error; - } - /* now set the memory regions */ -#if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1) - /* Note: this test section will need moving before it could ever - work as the registers are not yet mapped ! */ - /* send the new SHARED MESSAGE AREA to the SEP */ - sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus); - - /* poll for SEP response */ - retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); - while (retval != 0xffffffff && retval != sep->shared_bus) - retval = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR1_REG_ADDR); - - /* check the return value (register) */ - if (retval != sep->shared_bus) { - error = -ENOMEM; - goto end_function_deallocate_sep_shared_area; - } -#endif - /* init the flow contextes */ - for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++) - sep->flows[counter].flow_id = SEP_FREE_FLOW_ID; - - sep->flow_wq = create_singlethread_workqueue("sepflowwq"); - if (sep->flow_wq == NULL) { - error = -ENOMEM; - edbg("sep_driver:flow queue creation failed\n"); - goto end_function_deallocate_sep_shared_area; - } - edbg("SEP Driver: create flow workqueue \n"); - sep->pdev = pci_dev_get(pdev); - - sep->reg_addr = pci_ioremap_bar(pdev, 0); - if (!sep->reg_addr) { - edbg("sep: ioremap of registers failed.\n"); - goto end_function_deallocate_sep_shared_area; - } - edbg("SEP Driver:reg_addr is %p\n", sep->reg_addr); - - /* load the rom code */ - sep_load_rom_code(sep); - - /* set up system base address and shared memory location */ - sep->rar_addr = dma_alloc_coherent(&sep->pdev->dev, - 2 * SEP_RAR_IO_MEM_REGION_SIZE, - &sep->rar_bus, GFP_KERNEL); - - if (!sep->rar_addr) { - edbg("SEP Driver:can't allocate rar\n"); - goto end_function_uniomap; - } - - - edbg("SEP Driver:rar_bus is %08llx\n", (unsigned long long)sep->rar_bus); - edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr); - -#if !SEP_DRIVER_POLLING_MODE - - edbg("SEP Driver: about to write IMR and ICR REG_ADDR\n"); - - /* clear ICR register */ - sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF); - - /* set the IMR register - open only GPR 2 */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); - - edbg("SEP Driver: about to call request_irq\n"); - /* get the interrupt line */ - error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED, "sep_driver", sep); - if (error) - goto end_function_free_res; - return 0; - edbg("SEP Driver: about to write IMR REG_ADDR"); - - /* set the IMR register - open only GPR 2 */ - sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, (~(0x1 << 13))); - -end_function_free_res: - dma_free_coherent(&sep->pdev->dev, 2 * SEP_RAR_IO_MEM_REGION_SIZE, - sep->rar_addr, sep->rar_bus); -#endif /* SEP_DRIVER_POLLING_MODE */ -end_function_uniomap: - iounmap(sep->reg_addr); -end_function_deallocate_sep_shared_area: - /* de-allocate shared area */ - sep_unmap_and_free_shared_area(sep, size); -end_function_error: - sep_dev = NULL; -end_function: - return error; -} - -static const struct pci_device_id sep_pci_id_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl); - -/* field for registering driver to PCI device */ -static struct pci_driver sep_pci_driver = { - .name = "sep_sec_driver", - .id_table = sep_pci_id_tbl, - .probe = sep_probe - /* FIXME: remove handler */ -}; - -/* major and minor device numbers */ -static dev_t sep_devno; - -/* the files operations structure of the driver */ -static struct file_operations sep_file_operations = { - .owner = THIS_MODULE, - .unlocked_ioctl = sep_ioctl, - .poll = sep_poll, - .open = sep_open, - .release = sep_release, - .mmap = sep_mmap, -}; - - -/* cdev struct of the driver */ -static struct cdev sep_cdev; - -/* - this function registers the driver to the file system -*/ -static int sep_register_driver_to_fs(void) -{ - int ret_val = alloc_chrdev_region(&sep_devno, 0, 1, "sep_sec_driver"); - if (ret_val) { - edbg("sep: major number allocation failed, retval is %d\n", - ret_val); - return ret_val; - } - /* init cdev */ - cdev_init(&sep_cdev, &sep_file_operations); - sep_cdev.owner = THIS_MODULE; - - /* register the driver with the kernel */ - ret_val = cdev_add(&sep_cdev, sep_devno, 1); - if (ret_val) { - edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val); - /* unregister dev numbers */ - unregister_chrdev_region(sep_devno, 1); - } - return ret_val; -} - - -/*-------------------------------------------------------------- - init function -----------------------------------------------------------------*/ -static int __init sep_init(void) -{ - int ret_val = 0; - dbg("SEP Driver:-------->Init start\n"); - /* FIXME: Probe can occur before we are ready to survive a probe */ - ret_val = pci_register_driver(&sep_pci_driver); - if (ret_val) { - edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val); - goto end_function_unregister_from_fs; - } - /* register driver to fs */ - ret_val = sep_register_driver_to_fs(); - if (ret_val) - goto end_function_unregister_pci; - goto end_function; -end_function_unregister_pci: - pci_unregister_driver(&sep_pci_driver); -end_function_unregister_from_fs: - /* unregister from fs */ - cdev_del(&sep_cdev); - /* unregister dev numbers */ - unregister_chrdev_region(sep_devno, 1); -end_function: - dbg("SEP Driver:<-------- Init end\n"); - return ret_val; -} - - -/*------------------------------------------------------------- - exit function ---------------------------------------------------------------*/ -static void __exit sep_exit(void) -{ - int size; - - dbg("SEP Driver:--------> Exit start\n"); - - /* unregister from fs */ - cdev_del(&sep_cdev); - /* unregister dev numbers */ - unregister_chrdev_region(sep_devno, 1); - /* calculate the total size for de-allocation */ - size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + - SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES + SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES + SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES; - /* FIXME: We need to do this in the unload for the device */ - /* free shared area */ - if (sep_dev) { - sep_unmap_and_free_shared_area(sep_dev, size); - edbg("SEP Driver: free pages SEP SHARED AREA \n"); - iounmap((void *) sep_dev->reg_addr); - edbg("SEP Driver: iounmap \n"); - } - edbg("SEP Driver: release_mem_region \n"); - dbg("SEP Driver:<-------- Exit end\n"); -} - - -module_init(sep_init); -module_exit(sep_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h deleted file mode 100644 index 7ef16da7c4ef..000000000000 --- a/drivers/staging/sep/sep_driver_api.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * - * sep_driver_api.h - Security Processor Driver api definitions - * - * Copyright(c) 2009 Intel Corporation. All rights reserved. - * Copyright(c) 2009 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; 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. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * - */ - -#ifndef __SEP_DRIVER_API_H__ -#define __SEP_DRIVER_API_H__ - - - -/*---------------------------------------------------------------- - IOCTL command defines - -----------------------------------------------------------------*/ - -/* magic number 1 of the sep IOCTL command */ -#define SEP_IOC_MAGIC_NUMBER 's' - -/* sends interrupt to sep that message is ready */ -#define SEP_IOCSENDSEPCOMMAND _IO(SEP_IOC_MAGIC_NUMBER , 0) - -/* sends interrupt to sep that message is ready */ -#define SEP_IOCSENDSEPRPLYCOMMAND _IO(SEP_IOC_MAGIC_NUMBER , 1) - -/* allocate memory in data pool */ -#define SEP_IOCALLOCDATAPOLL _IO(SEP_IOC_MAGIC_NUMBER , 2) - -/* write to pre-allocated memory in data pool */ -#define SEP_IOCWRITEDATAPOLL _IO(SEP_IOC_MAGIC_NUMBER , 3) - -/* read from pre-allocated memory in data pool */ -#define SEP_IOCREADDATAPOLL _IO(SEP_IOC_MAGIC_NUMBER , 4) - -/* create sym dma lli tables */ -#define SEP_IOCCREATESYMDMATABLE _IO(SEP_IOC_MAGIC_NUMBER , 5) - -/* create flow dma lli tables */ -#define SEP_IOCCREATEFLOWDMATABLE _IO(SEP_IOC_MAGIC_NUMBER , 6) - -/* free dynamic data aalocated during table creation */ -#define SEP_IOCFREEDMATABLEDATA _IO(SEP_IOC_MAGIC_NUMBER , 7) - -/* get the static pool area addresses (physical and virtual) */ -#define SEP_IOCGETSTATICPOOLADDR _IO(SEP_IOC_MAGIC_NUMBER , 8) - -/* set flow id command */ -#define SEP_IOCSETFLOWID _IO(SEP_IOC_MAGIC_NUMBER , 9) - -/* add tables to the dynamic flow */ -#define SEP_IOCADDFLOWTABLE _IO(SEP_IOC_MAGIC_NUMBER , 10) - -/* add flow add tables message */ -#define SEP_IOCADDFLOWMESSAGE _IO(SEP_IOC_MAGIC_NUMBER , 11) - -/* start sep command */ -#define SEP_IOCSEPSTART _IO(SEP_IOC_MAGIC_NUMBER , 12) - -/* init sep command */ -#define SEP_IOCSEPINIT _IO(SEP_IOC_MAGIC_NUMBER , 13) - -/* end transaction command */ -#define SEP_IOCENDTRANSACTION _IO(SEP_IOC_MAGIC_NUMBER , 15) - -/* reallocate cache and resident */ -#define SEP_IOCREALLOCCACHERES _IO(SEP_IOC_MAGIC_NUMBER , 16) - -/* get the offset of the address starting from the beginnnig of the map area */ -#define SEP_IOCGETMAPPEDADDROFFSET _IO(SEP_IOC_MAGIC_NUMBER , 17) - -/* get time address and value */ -#define SEP_IOCGETIME _IO(SEP_IOC_MAGIC_NUMBER , 19) - -/*------------------------------------------- - TYPEDEFS -----------------------------------------------*/ - -/* - init command struct -*/ -struct sep_driver_init_t { - /* start of the 1G of the host memory address that SEP can access */ - unsigned long message_addr; - - /* start address of resident */ - unsigned long message_size_in_words; - -}; - - -/* - realloc cache resident command -*/ -struct sep_driver_realloc_cache_resident_t { - /* new cache address */ - u64 new_cache_addr; - /* new resident address */ - u64 new_resident_addr; - /* new resident address */ - u64 new_shared_area_addr; - /* new base address */ - u64 new_base_addr; -}; - -struct sep_driver_alloc_t { - /* virtual address of allocated space */ - unsigned long offset; - - /* physical address of allocated space */ - unsigned long phys_address; - - /* number of bytes to allocate */ - unsigned long num_bytes; -}; - -/* - */ -struct sep_driver_write_t { - /* application space address */ - unsigned long app_address; - - /* address of the data pool */ - unsigned long datapool_address; - - /* number of bytes to write */ - unsigned long num_bytes; -}; - -/* - */ -struct sep_driver_read_t { - /* application space address */ - unsigned long app_address; - - /* address of the data pool */ - unsigned long datapool_address; - - /* number of bytes to read */ - unsigned long num_bytes; -}; - -/* -*/ -struct sep_driver_build_sync_table_t { - /* address value of the data in */ - unsigned long app_in_address; - - /* size of data in */ - unsigned long data_in_size; - - /* address of the data out */ - unsigned long app_out_address; - - /* the size of the block of the operation - if needed, - every table will be modulo this parameter */ - unsigned long block_size; - - /* the physical address of the first input DMA table */ - unsigned long in_table_address; - - /* number of entries in the first input DMA table */ - unsigned long in_table_num_entries; - - /* the physical address of the first output DMA table */ - unsigned long out_table_address; - - /* number of entries in the first output DMA table */ - unsigned long out_table_num_entries; - - /* data in the first input table */ - unsigned long table_data_size; - - /* distinct user/kernel layout */ - bool isKernelVirtualAddress; - -}; - -/* -*/ -struct sep_driver_build_flow_table_t { - /* flow type */ - unsigned long flow_type; - - /* flag for input output */ - unsigned long input_output_flag; - - /* address value of the data in */ - unsigned long virt_buff_data_addr; - - /* size of data in */ - unsigned long num_virtual_buffers; - - /* the physical address of the first input DMA table */ - unsigned long first_table_addr; - - /* number of entries in the first input DMA table */ - unsigned long first_table_num_entries; - - /* data in the first input table */ - unsigned long first_table_data_size; - - /* distinct user/kernel layout */ - bool isKernelVirtualAddress; -}; - - -struct sep_driver_add_flow_table_t { - /* flow id */ - unsigned long flow_id; - - /* flag for input output */ - unsigned long inputOutputFlag; - - /* address value of the data in */ - unsigned long virt_buff_data_addr; - - /* size of data in */ - unsigned long num_virtual_buffers; - - /* address of the first table */ - unsigned long first_table_addr; - - /* number of entries in the first table */ - unsigned long first_table_num_entries; - - /* data size of the first table */ - unsigned long first_table_data_size; - - /* distinct user/kernel layout */ - bool isKernelVirtualAddress; - -}; - -/* - command struct for set flow id -*/ -struct sep_driver_set_flow_id_t { - /* flow id to set */ - unsigned long flow_id; -}; - - -/* command struct for add tables message */ -struct sep_driver_add_message_t { - /* flow id to set */ - unsigned long flow_id; - - /* message size in bytes */ - unsigned long message_size_in_bytes; - - /* address of the message */ - unsigned long message_address; -}; - -/* command struct for static pool addresses */ -struct sep_driver_static_pool_addr_t { - /* physical address of the static pool */ - unsigned long physical_static_address; - - /* virtual address of the static pool */ - unsigned long virtual_static_address; -}; - -/* command struct for getiing offset of the physical address from - the start of the mapped area */ -struct sep_driver_get_mapped_offset_t { - /* physical address of the static pool */ - unsigned long physical_address; - - /* virtual address of the static pool */ - unsigned long offset; -}; - -/* command struct for getting time value and address */ -struct sep_driver_get_time_t { - /* physical address of stored time */ - unsigned long time_physical_address; - - /* value of the stored time */ - unsigned long time_value; -}; - - -/* - structure that represent one entry in the DMA LLI table -*/ -struct sep_lli_entry_t { - /* physical address */ - unsigned long physical_address; - - /* block size */ - unsigned long block_size; -}; - -/* - structure that reperesents data needed for lli table construction -*/ -struct sep_lli_prepare_table_data_t { - /* pointer to the memory where the first lli entry to be built */ - struct sep_lli_entry_t *lli_entry_ptr; - - /* pointer to the array of lli entries from which the table is to be built */ - struct sep_lli_entry_t *lli_array_ptr; - - /* number of elements in lli array */ - int lli_array_size; - - /* number of entries in the created table */ - int num_table_entries; - - /* number of array entries processed during table creation */ - int num_array_entries_processed; - - /* the totatl data size in the created table */ - int lli_table_total_data_size; -}; - -/* - structure that represent tone table - it is not used in code, jkust - to show what table looks like -*/ -struct sep_lli_table_t { - /* number of pages mapped in this tables. If 0 - means that the table - is not defined (used as a valid flag) */ - unsigned long num_pages; - /* - pointer to array of page pointers that represent the mapping of the - virtual buffer defined by the table to the physical memory. If this - pointer is NULL, it means that the table is not defined - (used as a valid flag) - */ - struct page **table_page_array_ptr; - - /* maximum flow entries in table */ - struct sep_lli_entry_t lli_entries[SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE]; -}; - - -/* - structure for keeping the mapping of the virtual buffer into physical pages -*/ -struct sep_flow_buffer_data { - /* pointer to the array of page structs pointers to the pages of the - virtual buffer */ - struct page **page_array_ptr; - - /* number of pages taken by the virtual buffer */ - unsigned long num_pages; - - /* this flag signals if this page_array is the last one among many that were - sent in one setting to SEP */ - unsigned long last_page_array_flag; -}; - -/* - struct that keeps all the data for one flow -*/ -struct sep_flow_context_t { - /* - work struct for handling the flow done interrupt in the workqueue - this structure must be in the first place, since it will be used - forcasting to the containing flow context - */ - struct work_struct flow_wq; - - /* flow id */ - unsigned long flow_id; - - /* additional input tables exists */ - unsigned long input_tables_flag; - - /* additional output tables exists */ - unsigned long output_tables_flag; - - /* data of the first input file */ - struct sep_lli_entry_t first_input_table; - - /* data of the first output table */ - struct sep_lli_entry_t first_output_table; - - /* last input table data */ - struct sep_lli_entry_t last_input_table; - - /* last output table data */ - struct sep_lli_entry_t last_output_table; - - /* first list of table */ - struct sep_lli_entry_t input_tables_in_process; - - /* output table in process (in sep) */ - struct sep_lli_entry_t output_tables_in_process; - - /* size of messages in bytes */ - unsigned long message_size_in_bytes; - - /* message */ - unsigned char message[SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES]; -}; - - -#endif diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h deleted file mode 100644 index 6008fe5eca09..000000000000 --- a/drivers/staging/sep/sep_driver_config.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * - * sep_driver_config.h - Security Processor Driver configuration - * - * Copyright(c) 2009 Intel Corporation. All rights reserved. - * Copyright(c) 2009 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; 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. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * - */ - -#ifndef __SEP_DRIVER_CONFIG_H__ -#define __SEP_DRIVER_CONFIG_H__ - - -/*-------------------------------------- - DRIVER CONFIGURATION FLAGS - -------------------------------------*/ - -/* if flag is on , then the driver is running in polling and - not interrupt mode */ -#define SEP_DRIVER_POLLING_MODE 1 - -/* flag which defines if the shared area address should be - reconfiged (send to SEP anew) during init of the driver */ -#define SEP_DRIVER_RECONFIG_MESSAGE_AREA 0 - -/* the mode for running on the ARM1172 Evaluation platform (flag is 1) */ -#define SEP_DRIVER_ARM_DEBUG_MODE 0 - -/*------------------------------------------- - INTERNAL DATA CONFIGURATION - -------------------------------------------*/ - -/* flag for the input array */ -#define SEP_DRIVER_IN_FLAG 0 - -/* flag for output array */ -#define SEP_DRIVER_OUT_FLAG 1 - -/* maximum number of entries in one LLI tables */ -#define SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP 8 - - -/*-------------------------------------------------------- - SHARED AREA memory total size is 36K - it is divided is following: - - SHARED_MESSAGE_AREA 8K } - } - STATIC_POOL_AREA 4K } MAPPED AREA ( 24 K) - } - DATA_POOL_AREA 12K } - - SYNCHRONIC_DMA_TABLES_AREA 5K - - FLOW_DMA_TABLES_AREA 4K - - SYSTEM_MEMORY_AREA 3k - - SYSTEM_MEMORY total size is 3k - it is divided as following: - - TIME_MEMORY_AREA 8B ------------------------------------------------------------*/ - - - -/* - the maximum length of the message - the rest of the message shared - area will be dedicated to the dma lli tables -*/ -#define SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES (8 * 1024) - -/* the size of the message shared area in pages */ -#define SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES (8 * 1024) - -/* the size of the data pool static area in pages */ -#define SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES (4 * 1024) - -/* the size of the data pool shared area size in pages */ -#define SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES (12 * 1024) - -/* the size of the message shared area in pages */ -#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES (1024 * 5) - - -/* the size of the data pool shared area size in pages */ -#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES (1024 * 4) - -/* system data (time, caller id etc') pool */ -#define SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES 100 - - -/* area size that is mapped - we map the MESSAGE AREA, STATIC POOL and - DATA POOL areas. area must be module 4k */ -#define SEP_DRIVER_MMMAP_AREA_SIZE (1024 * 24) - - -/*----------------------------------------------- - offsets of the areas starting from the shared area start address -*/ - -/* message area offset */ -#define SEP_DRIVER_MESSAGE_AREA_OFFSET_IN_BYTES 0 - -/* static pool area offset */ -#define SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES \ - (SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES) - -/* data pool area offset */ -#define SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES \ - (SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES + \ - SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES) - -/* synhronic dma tables area offset */ -#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES \ - (SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + \ - SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) - -/* sep driver flow dma tables area offset */ -#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES \ - (SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES + \ - SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES) - -/* system memory offset in bytes */ -#define SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES \ - (SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES + \ - SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES) - -/* offset of the time area */ -#define SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES \ - (SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES) - - - -/* start physical address of the SEP registers memory in HOST */ -#define SEP_IO_MEM_REGION_START_ADDRESS 0x80000000 - -/* size of the SEP registers memory region in HOST (for now 100 registers) */ -#define SEP_IO_MEM_REGION_SIZE (2 * 0x100000) - -/* define the number of IRQ for SEP interrupts */ -#define SEP_DIRVER_IRQ_NUM 1 - -/* maximum number of add buffers */ -#define SEP_MAX_NUM_ADD_BUFFERS 100 - -/* number of flows */ -#define SEP_DRIVER_NUM_FLOWS 4 - -/* maximum number of entries in flow table */ -#define SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE 25 - -/* offset of the num entries in the block length entry of the LLI */ -#define SEP_NUM_ENTRIES_OFFSET_IN_BITS 24 - -/* offset of the interrupt flag in the block length entry of the LLI */ -#define SEP_INT_FLAG_OFFSET_IN_BITS 31 - -/* mask for extracting data size from LLI */ -#define SEP_TABLE_DATA_SIZE_MASK 0xFFFFFF - -/* mask for entries after being shifted left */ -#define SEP_NUM_ENTRIES_MASK 0x7F - -/* default flow id */ -#define SEP_FREE_FLOW_ID 0xFFFFFFFF - -/* temp flow id used during cretiong of new flow until receiving - real flow id from sep */ -#define SEP_TEMP_FLOW_ID (SEP_DRIVER_NUM_FLOWS + 1) - -/* maximum add buffers message length in bytes */ -#define SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES (7 * 4) - -/* maximum number of concurrent virtual buffers */ -#define SEP_MAX_VIRT_BUFFERS_CONCURRENT 100 - -/* the token that defines the start of time address */ -#define SEP_TIME_VAL_TOKEN 0x12345678 - -/* DEBUG LEVEL MASKS */ -#define SEP_DEBUG_LEVEL_BASIC 0x1 - -#define SEP_DEBUG_LEVEL_EXTENDED 0x4 - - -/* Debug helpers */ - -#define dbg(fmt, args...) \ -do {\ - if (debug & SEP_DEBUG_LEVEL_BASIC) \ - printk(KERN_DEBUG fmt, ##args); \ -} while(0); - -#define edbg(fmt, args...) \ -do { \ - if (debug & SEP_DEBUG_LEVEL_EXTENDED) \ - printk(KERN_DEBUG fmt, ##args); \ -} while(0); - - - -#endif diff --git a/drivers/staging/sep/sep_driver_hw_defs.h b/drivers/staging/sep/sep_driver_hw_defs.h deleted file mode 100644 index ea6abd8a14b4..000000000000 --- a/drivers/staging/sep/sep_driver_hw_defs.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * - * sep_driver_hw_defs.h - Security Processor Driver hardware definitions - * - * Copyright(c) 2009 Intel Corporation. All rights reserved. - * Copyright(c) 2009 Discretix. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; 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. - * - * CONTACTS: - * - * Mark Allyn mark.a.allyn@intel.com - * - * CHANGES: - * - * 2009.06.26 Initial publish - * - */ - -#ifndef SEP_DRIVER_HW_DEFS__H -#define SEP_DRIVER_HW_DEFS__H - -/*--------------------------------------------------------------------------*/ -/* Abstract: HW Registers Defines. */ -/* */ -/* Note: This file was automatically created !!! */ -/* DO NOT EDIT THIS FILE !!! */ -/*--------------------------------------------------------------------------*/ - - -/* cf registers */ -#define HW_R0B_ADDR_0_REG_ADDR 0x0000UL -#define HW_R0B_ADDR_1_REG_ADDR 0x0004UL -#define HW_R0B_ADDR_2_REG_ADDR 0x0008UL -#define HW_R0B_ADDR_3_REG_ADDR 0x000cUL -#define HW_R0B_ADDR_4_REG_ADDR 0x0010UL -#define HW_R0B_ADDR_5_REG_ADDR 0x0014UL -#define HW_R0B_ADDR_6_REG_ADDR 0x0018UL -#define HW_R0B_ADDR_7_REG_ADDR 0x001cUL -#define HW_R0B_ADDR_8_REG_ADDR 0x0020UL -#define HW_R2B_ADDR_0_REG_ADDR 0x0080UL -#define HW_R2B_ADDR_1_REG_ADDR 0x0084UL -#define HW_R2B_ADDR_2_REG_ADDR 0x0088UL -#define HW_R2B_ADDR_3_REG_ADDR 0x008cUL -#define HW_R2B_ADDR_4_REG_ADDR 0x0090UL -#define HW_R2B_ADDR_5_REG_ADDR 0x0094UL -#define HW_R2B_ADDR_6_REG_ADDR 0x0098UL -#define HW_R2B_ADDR_7_REG_ADDR 0x009cUL -#define HW_R2B_ADDR_8_REG_ADDR 0x00a0UL -#define HW_R3B_REG_ADDR 0x00C0UL -#define HW_R4B_REG_ADDR 0x0100UL -#define HW_CSA_ADDR_0_REG_ADDR 0x0140UL -#define HW_CSA_ADDR_1_REG_ADDR 0x0144UL -#define HW_CSA_ADDR_2_REG_ADDR 0x0148UL -#define HW_CSA_ADDR_3_REG_ADDR 0x014cUL -#define HW_CSA_ADDR_4_REG_ADDR 0x0150UL -#define HW_CSA_ADDR_5_REG_ADDR 0x0154UL -#define HW_CSA_ADDR_6_REG_ADDR 0x0158UL -#define HW_CSA_ADDR_7_REG_ADDR 0x015cUL -#define HW_CSA_ADDR_8_REG_ADDR 0x0160UL -#define HW_CSA_REG_ADDR 0x0140UL -#define HW_SINB_REG_ADDR 0x0180UL -#define HW_SOUTB_REG_ADDR 0x0184UL -#define HW_PKI_CONTROL_REG_ADDR 0x01C0UL -#define HW_PKI_STATUS_REG_ADDR 0x01C4UL -#define HW_PKI_BUSY_REG_ADDR 0x01C8UL -#define HW_PKI_A_1025_REG_ADDR 0x01CCUL -#define HW_PKI_SDMA_CTL_REG_ADDR 0x01D0UL -#define HW_PKI_SDMA_OFFSET_REG_ADDR 0x01D4UL -#define HW_PKI_SDMA_POINTERS_REG_ADDR 0x01D8UL -#define HW_PKI_SDMA_DLENG_REG_ADDR 0x01DCUL -#define HW_PKI_SDMA_EXP_POINTERS_REG_ADDR 0x01E0UL -#define HW_PKI_SDMA_RES_POINTERS_REG_ADDR 0x01E4UL -#define HW_PKI_CLR_REG_ADDR 0x01E8UL -#define HW_PKI_SDMA_BUSY_REG_ADDR 0x01E8UL -#define HW_PKI_SDMA_FIRST_EXP_N_REG_ADDR 0x01ECUL -#define HW_PKI_SDMA_MUL_BY1_REG_ADDR 0x01F0UL -#define HW_PKI_SDMA_RMUL_SEL_REG_ADDR 0x01F4UL -#define HW_DES_KEY_0_REG_ADDR 0x0208UL -#define HW_DES_KEY_1_REG_ADDR 0x020CUL -#define HW_DES_KEY_2_REG_ADDR 0x0210UL -#define HW_DES_KEY_3_REG_ADDR 0x0214UL -#define HW_DES_KEY_4_REG_ADDR 0x0218UL -#define HW_DES_KEY_5_REG_ADDR 0x021CUL -#define HW_DES_CONTROL_0_REG_ADDR 0x0220UL -#define HW_DES_CONTROL_1_REG_ADDR 0x0224UL -#define HW_DES_IV_0_REG_ADDR 0x0228UL -#define HW_DES_IV_1_REG_ADDR 0x022CUL -#define HW_AES_KEY_0_ADDR_0_REG_ADDR 0x0400UL -#define HW_AES_KEY_0_ADDR_1_REG_ADDR 0x0404UL -#define HW_AES_KEY_0_ADDR_2_REG_ADDR 0x0408UL -#define HW_AES_KEY_0_ADDR_3_REG_ADDR 0x040cUL -#define HW_AES_KEY_0_ADDR_4_REG_ADDR 0x0410UL -#define HW_AES_KEY_0_ADDR_5_REG_ADDR 0x0414UL -#define HW_AES_KEY_0_ADDR_6_REG_ADDR 0x0418UL -#define HW_AES_KEY_0_ADDR_7_REG_ADDR 0x041cUL -#define HW_AES_KEY_0_REG_ADDR 0x0400UL -#define HW_AES_IV_0_ADDR_0_REG_ADDR 0x0440UL -#define HW_AES_IV_0_ADDR_1_REG_ADDR 0x0444UL -#define HW_AES_IV_0_ADDR_2_REG_ADDR 0x0448UL -#define HW_AES_IV_0_ADDR_3_REG_ADDR 0x044cUL -#define HW_AES_IV_0_REG_ADDR 0x0440UL -#define HW_AES_CTR1_ADDR_0_REG_ADDR 0x0460UL -#define HW_AES_CTR1_ADDR_1_REG_ADDR 0x0464UL -#define HW_AES_CTR1_ADDR_2_REG_ADDR 0x0468UL -#define HW_AES_CTR1_ADDR_3_REG_ADDR 0x046cUL -#define HW_AES_CTR1_REG_ADDR 0x0460UL -#define HW_AES_SK_REG_ADDR 0x0478UL -#define HW_AES_MAC_OK_REG_ADDR 0x0480UL -#define HW_AES_PREV_IV_0_ADDR_0_REG_ADDR 0x0490UL -#define HW_AES_PREV_IV_0_ADDR_1_REG_ADDR 0x0494UL -#define HW_AES_PREV_IV_0_ADDR_2_REG_ADDR 0x0498UL -#define HW_AES_PREV_IV_0_ADDR_3_REG_ADDR 0x049cUL -#define HW_AES_PREV_IV_0_REG_ADDR 0x0490UL -#define HW_AES_CONTROL_REG_ADDR 0x04C0UL -#define HW_HASH_H0_REG_ADDR 0x0640UL -#define HW_HASH_H1_REG_ADDR 0x0644UL -#define HW_HASH_H2_REG_ADDR 0x0648UL -#define HW_HASH_H3_REG_ADDR 0x064CUL -#define HW_HASH_H4_REG_ADDR 0x0650UL -#define HW_HASH_H5_REG_ADDR 0x0654UL -#define HW_HASH_H6_REG_ADDR 0x0658UL -#define HW_HASH_H7_REG_ADDR 0x065CUL -#define HW_HASH_H8_REG_ADDR 0x0660UL -#define HW_HASH_H9_REG_ADDR 0x0664UL -#define HW_HASH_H10_REG_ADDR 0x0668UL -#define HW_HASH_H11_REG_ADDR 0x066CUL -#define HW_HASH_H12_REG_ADDR 0x0670UL -#define HW_HASH_H13_REG_ADDR 0x0674UL -#define HW_HASH_H14_REG_ADDR 0x0678UL -#define HW_HASH_H15_REG_ADDR 0x067CUL -#define HW_HASH_CONTROL_REG_ADDR 0x07C0UL -#define HW_HASH_PAD_EN_REG_ADDR 0x07C4UL -#define HW_HASH_PAD_CFG_REG_ADDR 0x07C8UL -#define HW_HASH_CUR_LEN_0_REG_ADDR 0x07CCUL -#define HW_HASH_CUR_LEN_1_REG_ADDR 0x07D0UL -#define HW_HASH_CUR_LEN_2_REG_ADDR 0x07D4UL -#define HW_HASH_CUR_LEN_3_REG_ADDR 0x07D8UL -#define HW_HASH_PARAM_REG_ADDR 0x07DCUL -#define HW_HASH_INT_BUSY_REG_ADDR 0x07E0UL -#define HW_HASH_SW_RESET_REG_ADDR 0x07E4UL -#define HW_HASH_ENDIANESS_REG_ADDR 0x07E8UL -#define HW_HASH_DATA_REG_ADDR 0x07ECUL -#define HW_DRNG_CONTROL_REG_ADDR 0x0800UL -#define HW_DRNG_VALID_REG_ADDR 0x0804UL -#define HW_DRNG_DATA_REG_ADDR 0x0808UL -#define HW_RND_SRC_EN_REG_ADDR 0x080CUL -#define HW_AES_CLK_ENABLE_REG_ADDR 0x0810UL -#define HW_DES_CLK_ENABLE_REG_ADDR 0x0814UL -#define HW_HASH_CLK_ENABLE_REG_ADDR 0x0818UL -#define HW_PKI_CLK_ENABLE_REG_ADDR 0x081CUL -#define HW_CLK_STATUS_REG_ADDR 0x0824UL -#define HW_CLK_ENABLE_REG_ADDR 0x0828UL -#define HW_DRNG_SAMPLE_REG_ADDR 0x0850UL -#define HW_RND_SRC_CTL_REG_ADDR 0x0858UL -#define HW_CRYPTO_CTL_REG_ADDR 0x0900UL -#define HW_CRYPTO_STATUS_REG_ADDR 0x090CUL -#define HW_CRYPTO_BUSY_REG_ADDR 0x0910UL -#define HW_AES_BUSY_REG_ADDR 0x0914UL -#define HW_DES_BUSY_REG_ADDR 0x0918UL -#define HW_HASH_BUSY_REG_ADDR 0x091CUL -#define HW_CONTENT_REG_ADDR 0x0924UL -#define HW_VERSION_REG_ADDR 0x0928UL -#define HW_CONTEXT_ID_REG_ADDR 0x0930UL -#define HW_DIN_BUFFER_REG_ADDR 0x0C00UL -#define HW_DIN_MEM_DMA_BUSY_REG_ADDR 0x0c20UL -#define HW_SRC_LLI_MEM_ADDR_REG_ADDR 0x0c24UL -#define HW_SRC_LLI_WORD0_REG_ADDR 0x0C28UL -#define HW_SRC_LLI_WORD1_REG_ADDR 0x0C2CUL -#define HW_SRAM_SRC_ADDR_REG_ADDR 0x0c30UL -#define HW_DIN_SRAM_BYTES_LEN_REG_ADDR 0x0c34UL -#define HW_DIN_SRAM_DMA_BUSY_REG_ADDR 0x0C38UL -#define HW_WRITE_ALIGN_REG_ADDR 0x0C3CUL -#define HW_OLD_DATA_REG_ADDR 0x0C48UL -#define HW_WRITE_ALIGN_LAST_REG_ADDR 0x0C4CUL -#define HW_DOUT_BUFFER_REG_ADDR 0x0C00UL -#define HW_DST_LLI_WORD0_REG_ADDR 0x0D28UL -#define HW_DST_LLI_WORD1_REG_ADDR 0x0D2CUL -#define HW_DST_LLI_MEM_ADDR_REG_ADDR 0x0D24UL -#define HW_DOUT_MEM_DMA_BUSY_REG_ADDR 0x0D20UL -#define HW_SRAM_DEST_ADDR_REG_ADDR 0x0D30UL -#define HW_DOUT_SRAM_BYTES_LEN_REG_ADDR 0x0D34UL -#define HW_DOUT_SRAM_DMA_BUSY_REG_ADDR 0x0D38UL -#define HW_READ_ALIGN_REG_ADDR 0x0D3CUL -#define HW_READ_LAST_DATA_REG_ADDR 0x0D44UL -#define HW_RC4_THRU_CPU_REG_ADDR 0x0D4CUL -#define HW_AHB_SINGLE_REG_ADDR 0x0E00UL -#define HW_SRAM_DATA_REG_ADDR 0x0F00UL -#define HW_SRAM_ADDR_REG_ADDR 0x0F04UL -#define HW_SRAM_DATA_READY_REG_ADDR 0x0F08UL -#define HW_HOST_IRR_REG_ADDR 0x0A00UL -#define HW_HOST_IMR_REG_ADDR 0x0A04UL -#define HW_HOST_ICR_REG_ADDR 0x0A08UL -#define HW_HOST_SEP_SRAM_THRESHOLD_REG_ADDR 0x0A10UL -#define HW_HOST_SEP_BUSY_REG_ADDR 0x0A14UL -#define HW_HOST_SEP_LCS_REG_ADDR 0x0A18UL -#define HW_HOST_CC_SW_RST_REG_ADDR 0x0A40UL -#define HW_HOST_SEP_SW_RST_REG_ADDR 0x0A44UL -#define HW_HOST_FLOW_DMA_SW_INT0_REG_ADDR 0x0A80UL -#define HW_HOST_FLOW_DMA_SW_INT1_REG_ADDR 0x0A84UL -#define HW_HOST_FLOW_DMA_SW_INT2_REG_ADDR 0x0A88UL -#define HW_HOST_FLOW_DMA_SW_INT3_REG_ADDR 0x0A8cUL -#define HW_HOST_FLOW_DMA_SW_INT4_REG_ADDR 0x0A90UL -#define HW_HOST_FLOW_DMA_SW_INT5_REG_ADDR 0x0A94UL -#define HW_HOST_FLOW_DMA_SW_INT6_REG_ADDR 0x0A98UL -#define HW_HOST_FLOW_DMA_SW_INT7_REG_ADDR 0x0A9cUL -#define HW_HOST_SEP_HOST_GPR0_REG_ADDR 0x0B00UL -#define HW_HOST_SEP_HOST_GPR1_REG_ADDR 0x0B04UL -#define HW_HOST_SEP_HOST_GPR2_REG_ADDR 0x0B08UL -#define HW_HOST_SEP_HOST_GPR3_REG_ADDR 0x0B0CUL -#define HW_HOST_HOST_SEP_GPR0_REG_ADDR 0x0B80UL -#define HW_HOST_HOST_SEP_GPR1_REG_ADDR 0x0B84UL -#define HW_HOST_HOST_SEP_GPR2_REG_ADDR 0x0B88UL -#define HW_HOST_HOST_SEP_GPR3_REG_ADDR 0x0B8CUL -#define HW_HOST_HOST_ENDIAN_REG_ADDR 0x0B90UL -#define HW_HOST_HOST_COMM_CLK_EN_REG_ADDR 0x0B94UL -#define HW_CLR_SRAM_BUSY_REG_REG_ADDR 0x0F0CUL -#define HW_CC_SRAM_BASE_ADDRESS 0x5800UL - -#endif /* ifndef HW_DEFS */ diff --git a/drivers/staging/spectra/Kconfig b/drivers/staging/spectra/Kconfig index 5e2ffefb60af..d231ae27299d 100644 --- a/drivers/staging/spectra/Kconfig +++ b/drivers/staging/spectra/Kconfig @@ -2,6 +2,7 @@ menuconfig SPECTRA tristate "Denali Spectra Flash Translation Layer" depends on BLOCK + depends on X86_MRST default n ---help--- Enable the FTL pseudo-filesystem used with the NAND Flash diff --git a/drivers/staging/spectra/ffsport.c b/drivers/staging/spectra/ffsport.c index d0c5c97eda3e..fa21a0fd8e84 100644 --- a/drivers/staging/spectra/ffsport.c +++ b/drivers/staging/spectra/ffsport.c @@ -27,6 +27,8 @@ #include <linux/kthread.h> #include <linux/log2.h> #include <linux/init.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> /**** Helper functions used for Div, Remainder operation on u64 ****/ @@ -113,7 +115,6 @@ u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type) #define GLOB_SBD_NAME "nd" #define GLOB_SBD_IRQ_NUM (29) -#define GLOB_VERSION "driver version 20091110" #define GLOB_SBD_IOCTL_GC (0x7701) #define GLOB_SBD_IOCTL_WL (0x7702) @@ -272,13 +273,6 @@ static int get_res_blk_num_os(void) return res_blks; } -static void SBD_prepare_flush(struct request_queue *q, struct request *rq) -{ - rq->cmd_type = REQ_TYPE_LINUX_BLOCK; - /* rq->timeout = 5 * HZ; */ - rq->cmd[0] = REQ_LB_OP_FLUSH; -} - /* Transfer a full request. */ static int do_transfer(struct spectra_nand_dev *tr, struct request *req) { @@ -296,8 +290,7 @@ static int do_transfer(struct spectra_nand_dev *tr, struct request *req) IdentifyDeviceData.PagesPerBlock * res_blks_os; - if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && - req->cmd[0] == REQ_LB_OP_FLUSH) { + if (req->cmd_type & REQ_FLUSH) { if (force_flush_cache()) /* Fail to flush cache */ return -EIO; else @@ -597,11 +590,23 @@ int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode, return -ENOTTY; } +int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long arg) +{ + int ret; + + lock_kernel(); + ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg); + unlock_kernel(); + + return ret; +} + static struct block_device_operations GLOB_SBD_ops = { .owner = THIS_MODULE, .open = GLOB_SBD_open, .release = GLOB_SBD_release, - .locked_ioctl = GLOB_SBD_ioctl, + .ioctl = GLOB_SBD_unlocked_ioctl, .getgeo = GLOB_SBD_getgeo, }; @@ -650,8 +655,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which) /* Here we force report 512 byte hardware sector size to Kernel */ blk_queue_logical_block_size(dev->queue, 512); - blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH, - SBD_prepare_flush); + blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH); dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd"); if (IS_ERR(dev->thread)) { diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c index 134aa5166a8d..9b5218b6ada8 100644 --- a/drivers/staging/spectra/flash.c +++ b/drivers/staging/spectra/flash.c @@ -61,7 +61,6 @@ static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr, static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr, u8 cache_blk, u16 flag); static int FTL_Cache_Write(void); -static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr); static void FTL_Calculate_LRU(void); static u32 FTL_Get_Block_Index(u32 wBlockNum); @@ -86,8 +85,6 @@ static u32 FTL_Replace_MWBlock(void); static int FTL_Replace_Block(u64 blk_addr); static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX); -static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, u64 blk_addr); - struct device_info_tag DeviceInfo; struct flash_cache_tag Cache; static struct spectra_l2_cache_info cache_l2; @@ -775,7 +772,7 @@ static void dump_cache_l2_table(void) { struct list_head *p; struct spectra_l2_cache_list *pnd; - int n, i; + int n; n = 0; list_for_each(p, &cache_l2.table.list) { @@ -1538,79 +1535,6 @@ static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr) } /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Update_Block -* Inputs: pointer to buffer,page address,block address -* Outputs: PASS=0 / FAIL=1 -* Description: It updates the cache -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Update_Block(u8 *pData, - u64 old_page_addr, u64 blk_addr) -{ - int i, j; - u8 *buf = pData; - int wResult = PASS; - int wFoundInCache; - u64 page_addr; - u64 addr; - u64 old_blk_addr; - u16 page_offset; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - old_blk_addr = (u64)(old_page_addr >> - DeviceInfo.nBitsInBlockDataSize) * DeviceInfo.wBlockDataSize; - page_offset = (u16)(GLOB_u64_Remainder(old_page_addr, 2) >> - DeviceInfo.nBitsInPageDataSize); - - for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) { - page_addr = old_blk_addr + i * DeviceInfo.wPageDataSize; - if (i != page_offset) { - wFoundInCache = FAIL; - for (j = 0; j < CACHE_ITEM_NUM; j++) { - addr = Cache.array[j].address; - addr = FTL_Get_Physical_Block_Addr(addr) + - GLOB_u64_Remainder(addr, 2); - if ((addr >= page_addr) && addr < - (page_addr + Cache.cache_item_size)) { - wFoundInCache = PASS; - buf = Cache.array[j].buf; - Cache.array[j].changed = SET; -#if CMD_DMA -#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE - int_cache[ftl_cmd_cnt].item = j; - int_cache[ftl_cmd_cnt].cache.address = - Cache.array[j].address; - int_cache[ftl_cmd_cnt].cache.changed = - Cache.array[j].changed; -#endif -#endif - break; - } - } - if (FAIL == wFoundInCache) { - if (ERR == FTL_Cache_Read_All(g_pTempBuf, - page_addr)) { - wResult = FAIL; - break; - } - buf = g_pTempBuf; - } - } else { - buf = pData; - } - - if (FAIL == FTL_Cache_Write_All(buf, - blk_addr + (page_addr - old_blk_addr))) { - wResult = FAIL; - break; - } - } - - return wResult; -} - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: FTL_Copy_Block * Inputs: source block address * Destination block address @@ -1698,7 +1622,7 @@ static int get_l2_cache_blks(void) static int erase_l2_cache_blocks(void) { int i, ret = PASS; - u32 pblk, lblk; + u32 pblk, lblk = BAD_BLOCK; u64 addr; u32 *pbt = (u32 *)g_pBlockTable; @@ -2004,87 +1928,6 @@ static int search_l2_cache(u8 *buf, u64 logical_addr) return ret; } -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Cache_Write_Back -* Inputs: pointer to data cached in sys memory -* address of free block in flash -* Outputs: PASS=0 / FAIL=1 -* Description: writes all the pages of Cache Block to flash -* -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr) -{ - int i, j, iErase; - u64 old_page_addr, addr, phy_addr; - u32 *pbt = (u32 *)g_pBlockTable; - u32 lba; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - old_page_addr = FTL_Get_Physical_Block_Addr(blk_addr) + - GLOB_u64_Remainder(blk_addr, 2); - - iErase = (FAIL == FTL_Replace_Block(blk_addr)) ? PASS : FAIL; - - pbt[BLK_FROM_ADDR(blk_addr)] &= (~SPARE_BLOCK); - -#if CMD_DMA - p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free; - g_pBTDelta_Free += sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = (u32)(blk_addr >> - DeviceInfo.nBitsInBlockDataSize); - p_BTableChangesDelta->BT_Entry_Value = - pbt[(u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - for (i = 0; i < RETRY_TIMES; i++) { - if (PASS == iErase) { - phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); - if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { - lba = BLK_FROM_ADDR(blk_addr); - MARK_BLOCK_AS_BAD(pbt[lba]); - i = RETRY_TIMES; - break; - } - } - - for (j = 0; j < CACHE_ITEM_NUM; j++) { - addr = Cache.array[j].address; - if ((addr <= blk_addr) && - ((addr + Cache.cache_item_size) > blk_addr)) - cache_block_to_write = j; - } - - phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); - if (PASS == FTL_Cache_Update_Block(pData, - old_page_addr, phy_addr)) { - cache_block_to_write = UNHIT_CACHE_ITEM; - break; - } else { - iErase = PASS; - } - } - - if (i >= RETRY_TIMES) { - if (ERR == FTL_Flash_Error_Handle(pData, - old_page_addr, blk_addr)) - return ERR; - else - return FAIL; - } - - return PASS; -} - /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: FTL_Cache_Write_Page * Inputs: Pointer to buffer, page address, cache block number @@ -2370,159 +2213,6 @@ static int FTL_Write_Block_Table(int wForce) return 1; } -/****************************************************************** -* Function: GLOB_FTL_Flash_Format -* Inputs: none -* Outputs: PASS -* Description: The block table stores bad block info, including MDF+ -* blocks gone bad over the ages. Therefore, if we have a -* block table in place, then use it to scan for bad blocks -* If not, then scan for MDF. -* Now, a block table will only be found if spectra was already -* being used. For a fresh flash, we'll go thru scanning for -* MDF. If spectra was being used, then there is a chance that -* the MDF has been corrupted. Spectra avoids writing to the -* first 2 bytes of the spare area to all pages in a block. This -* covers all known flash devices. However, since flash -* manufacturers have no standard of where the MDF is stored, -* this cannot guarantee that the MDF is protected for future -* devices too. The initial scanning for the block table assures -* this. It is ok even if the block table is outdated, as all -* we're looking for are bad block markers. -* Use this when mounting a file system or starting a -* new flash. -* -*********************************************************************/ -static int FTL_Format_Flash(u8 valid_block_table) -{ - u32 i, j; - u32 *pbt = (u32 *)g_pBlockTable; - u32 tempNode; - int ret; - -#if CMD_DMA - u32 *pbtStartingCopy = (u32 *)g_pBTStartingCopy; - if (ftl_cmd_cnt) - return FAIL; -#endif - - if (FAIL == FTL_Check_Block_Table(FAIL)) - valid_block_table = 0; - - if (valid_block_table) { - u8 switched = 1; - u32 block, k; - - k = DeviceInfo.wSpectraStartBlock; - while (switched && (k < DeviceInfo.wSpectraEndBlock)) { - switched = 0; - k++; - for (j = DeviceInfo.wSpectraStartBlock, i = 0; - j <= DeviceInfo.wSpectraEndBlock; - j++, i++) { - block = (pbt[i] & ~BAD_BLOCK) - - DeviceInfo.wSpectraStartBlock; - if (block != i) { - switched = 1; - tempNode = pbt[i]; - pbt[i] = pbt[block]; - pbt[block] = tempNode; - } - } - } - if ((k == DeviceInfo.wSpectraEndBlock) && switched) - valid_block_table = 0; - } - - if (!valid_block_table) { - memset(g_pBlockTable, 0, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memset(g_pWearCounter, 0, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memset(g_pReadCounter, 0, - DeviceInfo.wDataBlockNum * sizeof(u16)); -#if CMD_DMA - memset(g_pBTStartingCopy, 0, - DeviceInfo.wDataBlockNum * sizeof(u32)); - memset(g_pWearCounterCopy, 0, - DeviceInfo.wDataBlockNum * sizeof(u8)); - if (DeviceInfo.MLCDevice) - memset(g_pReadCounterCopy, 0, - DeviceInfo.wDataBlockNum * sizeof(u16)); -#endif - for (j = DeviceInfo.wSpectraStartBlock, i = 0; - j <= DeviceInfo.wSpectraEndBlock; - j++, i++) { - if (GLOB_LLD_Get_Bad_Block((u32)j)) - pbt[i] = (u32)(BAD_BLOCK | j); - } - } - - nand_dbg_print(NAND_DBG_WARN, "Erasing all blocks in the NAND\n"); - - for (j = DeviceInfo.wSpectraStartBlock, i = 0; - j <= DeviceInfo.wSpectraEndBlock; - j++, i++) { - if ((pbt[i] & BAD_BLOCK) != BAD_BLOCK) { - ret = GLOB_LLD_Erase_Block(j); - if (FAIL == ret) { - pbt[i] = (u32)(j); - MARK_BLOCK_AS_BAD(pbt[i]); - nand_dbg_print(NAND_DBG_WARN, - "NAND Program fail in %s, Line %d, " - "Function: %s, new Bad Block %d generated!\n", - __FILE__, __LINE__, __func__, (int)j); - } else { - pbt[i] = (u32)(SPARE_BLOCK | j); - } - } -#if CMD_DMA - pbtStartingCopy[i] = pbt[i]; -#endif - } - - g_wBlockTableOffset = 0; - for (i = 0; (i <= (DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock)) - && ((pbt[i] & BAD_BLOCK) == BAD_BLOCK); i++) - ; - if (i > (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock)) { - printk(KERN_ERR "All blocks bad!\n"); - return FAIL; - } else { - g_wBlockTableIndex = pbt[i] & ~BAD_BLOCK; - if (i != BLOCK_TABLE_INDEX) { - tempNode = pbt[i]; - pbt[i] = pbt[BLOCK_TABLE_INDEX]; - pbt[BLOCK_TABLE_INDEX] = tempNode; - } - } - pbt[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); - -#if CMD_DMA - pbtStartingCopy[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK); -#endif - - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - memset(g_pBTBlocks, 0xFF, - (1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32)); - g_pBTBlocks[FIRST_BT_ID-FIRST_BT_ID] = g_wBlockTableIndex; - FTL_Write_Block_Table(FAIL); - - for (i = 0; i < CACHE_ITEM_NUM; i++) { - Cache.array[i].address = NAND_CACHE_INIT_ADDR; - Cache.array[i].use_cnt = 0; - Cache.array[i].changed = CLEAR; - } - -#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA) - memcpy((void *)&cache_start_copy, (void *)&Cache, - sizeof(struct flash_cache_tag)); -#endif - return PASS; -} - static int force_format_nand(void) { u32 i; @@ -3031,112 +2721,6 @@ static int FTL_Read_Block_Table(void) return wResult; } - -/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& -* Function: FTL_Flash_Error_Handle -* Inputs: Pointer to data -* Page address -* Block address -* Outputs: PASS=0 / FAIL=1 -* Description: It handles any error occured during Spectra operation -*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ -static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, - u64 blk_addr) -{ - u32 i; - int j; - u32 tmp_node, blk_node = BLK_FROM_ADDR(blk_addr); - u64 phy_addr; - int wErase = FAIL; - int wResult = FAIL; - u32 *pbt = (u32 *)g_pBlockTable; - - nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", - __FILE__, __LINE__, __func__); - - if (ERR == GLOB_FTL_Garbage_Collection()) - return ERR; - - do { - for (i = DeviceInfo.wSpectraEndBlock - - DeviceInfo.wSpectraStartBlock; - i > 0; i--) { - if (IS_SPARE_BLOCK(i)) { - tmp_node = (u32)(BAD_BLOCK | - pbt[blk_node]); - pbt[blk_node] = (u32)(pbt[i] & - (~SPARE_BLOCK)); - pbt[i] = tmp_node; -#if CMD_DMA - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = - blk_node; - p_BTableChangesDelta->BT_Entry_Value = - pbt[blk_node]; - p_BTableChangesDelta->ValidFields = 0x0C; - - p_BTableChangesDelta = - (struct BTableChangesDelta *) - g_pBTDelta_Free; - g_pBTDelta_Free += - sizeof(struct BTableChangesDelta); - - p_BTableChangesDelta->ftl_cmd_cnt = - ftl_cmd_cnt; - p_BTableChangesDelta->BT_Index = i; - p_BTableChangesDelta->BT_Entry_Value = pbt[i]; - p_BTableChangesDelta->ValidFields = 0x0C; -#endif - wResult = PASS; - break; - } - } - - if (FAIL == wResult) { - if (FAIL == GLOB_FTL_Garbage_Collection()) - break; - else - continue; - } - - if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) { - g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE; - FTL_Write_IN_Progress_Block_Table_Page(); - } - - phy_addr = FTL_Get_Physical_Block_Addr(blk_addr); - - for (j = 0; j < RETRY_TIMES; j++) { - if (PASS == wErase) { - if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) { - MARK_BLOCK_AS_BAD(pbt[blk_node]); - break; - } - } - if (PASS == FTL_Cache_Update_Block(pData, - old_page_addr, - phy_addr)) { - wResult = PASS; - break; - } else { - wResult = FAIL; - wErase = PASS; - } - } - } while (FAIL == wResult); - - FTL_Write_Block_Table(FAIL); - - return wResult; -} - /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: FTL_Get_Page_Num * Inputs: Size in bytes diff --git a/drivers/staging/ti-st/st.h b/drivers/staging/ti-st/st.h index 9952579425b9..1b3060eb2921 100644 --- a/drivers/staging/ti-st/st.h +++ b/drivers/staging/ti-st/st.h @@ -80,5 +80,4 @@ struct st_proto_s { extern long st_register(struct st_proto_s *); extern long st_unregister(enum proto_type); -extern struct platform_device *st_get_plat_device(void); #endif /* ST_H */ diff --git a/drivers/staging/ti-st/st_core.c b/drivers/staging/ti-st/st_core.c index 063c9b1db1ab..b85d8bfdf600 100644 --- a/drivers/staging/ti-st/st_core.c +++ b/drivers/staging/ti-st/st_core.c @@ -38,7 +38,6 @@ #include "st_ll.h" #include "st.h" -#define VERBOSE /* strings to be used for rfkill entries and by * ST Core to be used for sysfs debug entry */ @@ -581,7 +580,7 @@ long st_register(struct st_proto_s *new_proto) long err = 0; unsigned long flags = 0; - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); pr_info("%s(%d) ", __func__, new_proto->type); if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL || new_proto->reg_complete_cb == NULL) { @@ -713,7 +712,7 @@ long st_unregister(enum proto_type type) pr_debug("%s: %d ", __func__, type); - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); if (type < ST_BT || type >= ST_MAX) { pr_err(" protocol %d not supported", type); return -EPROTONOSUPPORT; @@ -767,7 +766,7 @@ long st_write(struct sk_buff *skb) #endif long len; - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); if (unlikely(skb == NULL || st_gdata == NULL || st_gdata->tty == NULL)) { pr_err("data/tty unavailable to perform write"); @@ -818,7 +817,7 @@ static int st_tty_open(struct tty_struct *tty) struct st_data_s *st_gdata; pr_info("%s ", __func__); - st_kim_ref(&st_gdata); + st_kim_ref(&st_gdata, 0); st_gdata->tty = tty; tty->disc_data = st_gdata; diff --git a/drivers/staging/ti-st/st_core.h b/drivers/staging/ti-st/st_core.h index e0c32d149f5f..8601320a679e 100644 --- a/drivers/staging/ti-st/st_core.h +++ b/drivers/staging/ti-st/st_core.h @@ -117,7 +117,7 @@ int st_core_init(struct st_data_s **); void st_core_exit(struct st_data_s *); /* ask for reference from KIM */ -void st_kim_ref(struct st_data_s **); +void st_kim_ref(struct st_data_s **, int); #define GPS_STUB_TEST #ifdef GPS_STUB_TEST diff --git a/drivers/staging/ti-st/st_kim.c b/drivers/staging/ti-st/st_kim.c index b4a6c7fdc4e6..9e99463f76e8 100644 --- a/drivers/staging/ti-st/st_kim.c +++ b/drivers/staging/ti-st/st_kim.c @@ -72,11 +72,26 @@ const unsigned char *protocol_names[] = { PROTO_ENTRY(ST_GPS, "GPS"), }; +#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */ +struct platform_device *st_kim_devices[MAX_ST_DEVICES]; /**********************************************************************/ /* internal functions */ /** + * st_get_plat_device - + * function which returns the reference to the platform device + * requested by id. As of now only 1 such device exists (id=0) + * the context requesting for reference can get the id to be + * requested by a. The protocol driver which is registering or + * b. the tty device which is opened. + */ +static struct platform_device *st_get_plat_device(int id) +{ + return st_kim_devices[id]; +} + +/** * validate_firmware_response - * function to return whether the firmware response was proper * in case of error don't complete so that waiting for proper @@ -353,7 +368,7 @@ void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state) struct kim_data_s *kim_gdata; pr_info(" %s ", __func__); - kim_pdev = st_get_plat_device(); + kim_pdev = st_get_plat_device(0); kim_gdata = dev_get_drvdata(&kim_pdev->dev); if (kim_gdata->gpios[type] == -1) { @@ -574,12 +589,12 @@ static int kim_toggle_radio(void *data, bool blocked) * This would enable multiple such platform devices to exist * on a given platform */ -void st_kim_ref(struct st_data_s **core_data) +void st_kim_ref(struct st_data_s **core_data, int id) { struct platform_device *pdev; struct kim_data_s *kim_gdata; /* get kim_gdata reference from platform device */ - pdev = st_get_plat_device(); + pdev = st_get_plat_device(id); kim_gdata = dev_get_drvdata(&pdev->dev); *core_data = kim_gdata->core_data; } @@ -623,6 +638,7 @@ static int kim_probe(struct platform_device *pdev) long *gpios = pdev->dev.platform_data; struct kim_data_s *kim_gdata; + st_kim_devices[pdev->id] = pdev; kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_ATOMIC); if (!kim_gdata) { pr_err("no mem to allocate"); diff --git a/drivers/staging/tm6000/Kconfig b/drivers/staging/tm6000/Kconfig index c725356cc346..de7ebb99d8f6 100644 --- a/drivers/staging/tm6000/Kconfig +++ b/drivers/staging/tm6000/Kconfig @@ -1,6 +1,6 @@ config VIDEO_TM6000 tristate "TV Master TM5600/6000/6010 driver" - depends on VIDEO_DEV && I2C && INPUT && USB && EXPERIMENTAL + depends on VIDEO_DEV && I2C && INPUT && IR_CORE && USB && EXPERIMENTAL select VIDEO_TUNER select MEDIA_TUNER_XC2028 select MEDIA_TUNER_XC5000 diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c index 32f7a0af6938..54f7667cc706 100644 --- a/drivers/staging/tm6000/tm6000-input.c +++ b/drivers/staging/tm6000/tm6000-input.c @@ -46,7 +46,7 @@ MODULE_PARM_DESC(enable_ir, "enable ir (default is enable"); } struct tm6000_ir_poll_result { - u8 rc_data[4]; + u16 rc_data; }; struct tm6000_IR { @@ -60,9 +60,9 @@ struct tm6000_IR { int polling; struct delayed_work work; u8 wait:1; + u8 key:1; struct urb *int_urb; u8 *urb_data; - u8 key:1; int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); @@ -122,13 +122,14 @@ static void tm6000_ir_urb_received(struct urb *urb) if (urb->status != 0) printk(KERN_INFO "not ready\n"); - else if (urb->actual_length > 0) + else if (urb->actual_length > 0) { memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); - dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], - ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); + dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], + ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); - ir->key = 1; + ir->key = 1; + } rc = usb_submit_urb(urb, GFP_ATOMIC); } @@ -140,30 +141,47 @@ static int default_polling_getkey(struct tm6000_IR *ir, int rc; u8 buf[2]; - if (ir->wait && !&dev->int_in) { - poll_result->rc_data[0] = 0xff; + if (ir->wait && !&dev->int_in) return 0; - } if (&dev->int_in) { - poll_result->rc_data[0] = ir->urb_data[0]; - poll_result->rc_data[1] = ir->urb_data[1]; + if (ir->ir.ir_type == IR_TYPE_RC5) + poll_result->rc_data = ir->urb_data[0]; + else + poll_result->rc_data = ir->urb_data[0] | ir->urb_data[1] << 8; } else { tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); msleep(10); tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); msleep(10); - rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, REQ_02_GET_IR_CODE, 0, 0, buf, 1); + if (ir->ir.ir_type == IR_TYPE_RC5) { + rc = tm6000_read_write_usb(dev, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + REQ_02_GET_IR_CODE, 0, 0, buf, 1); - msleep(10); + msleep(10); - dprintk("read data=%02x\n", buf[0]); - if (rc < 0) - return rc; + dprintk("read data=%02x\n", buf[0]); + if (rc < 0) + return rc; - poll_result->rc_data[0] = buf[0]; + poll_result->rc_data = buf[0]; + } else { + rc = tm6000_read_write_usb(dev, USB_DIR_IN | + USB_TYPE_VENDOR | USB_RECIP_DEVICE, + REQ_02_GET_IR_CODE, 0, 0, buf, 2); + + msleep(10); + + dprintk("read data=%04x\n", buf[0] | buf[1] << 8); + if (rc < 0) + return rc; + + poll_result->rc_data = buf[0] | buf[1] << 8; + } + if ((poll_result->rc_data & 0x00ff) != 0xff) + ir->key = 1; } return 0; } @@ -180,12 +198,11 @@ static void tm6000_ir_handle_key(struct tm6000_IR *ir) return; } - dprintk("ir->get_key result data=%02x %02x\n", - poll_result.rc_data[0], poll_result.rc_data[1]); + dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); - if (poll_result.rc_data[0] != 0xff && ir->key == 1) { + if (ir->key) { ir_input_keydown(ir->input->input_dev, &ir->ir, - poll_result.rc_data[0] | poll_result.rc_data[1] << 8); + (u32)poll_result.rc_data); ir_input_nokey(ir->input->input_dev, &ir->ir); ir->key = 0; diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c index 0142338bcafe..4bdb8362de82 100644 --- a/drivers/staging/vt6655/wpactl.c +++ b/drivers/staging/vt6655/wpactl.c @@ -766,9 +766,14 @@ static int wpa_set_associate(PSDevice pDevice, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len); - if (param->u.wpa_associate.wpa_ie && - copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) - return -EINVAL; + if (param->u.wpa_associate.wpa_ie_len) { + if (!param->u.wpa_associate.wpa_ie) + return -EINVAL; + if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE)) + return -EINVAL; + if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie, param->u.wpa_associate.wpa_ie_len)) + return -EFAULT; + } if (param->u.wpa_associate.mode == 1) pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA; diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 368c30a9d5ff..4af83d5318f2 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -219,6 +219,7 @@ int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, return -ENOENT; params.key_len = len; params.key = wlandev->wep_keys[key_index]; + params.seq_len = 0; callback(cookie, ¶ms); @@ -735,6 +736,8 @@ struct wiphy *wlan_create_wiphy(struct device *dev, wlandevice_t *wlandev) priv->band.n_channels = ARRAY_SIZE(prism2_channels); priv->band.bitrates = priv->rates; priv->band.n_bitrates = ARRAY_SIZE(prism2_rates); + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.ht_cap.ht_supported = false; wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; set_wiphy_dev(wiphy, dev); diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 77d4d715a789..722c840ac638 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -769,6 +769,7 @@ static int __init zram_init(void) free_devices: while (dev_id) destroy_device(&devices[--dev_id]); + kfree(devices); unregister: unregister_blkdev(zram_major, "zram"); out: diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 593fc5e2d2e6..5af23cc5ea9f 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -1127,6 +1127,7 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, { struct cxacru_data *instance; struct usb_device *usb_dev = interface_to_usbdev(intf); + struct usb_host_endpoint *cmd_ep = usb_dev->ep_in[CXACRU_EP_CMD]; int ret; /* instance init */ @@ -1171,15 +1172,34 @@ static int cxacru_bind(struct usbatm_data *usbatm_instance, goto fail; } - usb_fill_int_urb(instance->rcv_urb, + if (!cmd_ep) { + dbg("cxacru_bind: no command endpoint"); + ret = -ENODEV; + goto fail; + } + + if ((cmd_ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT) { + usb_fill_int_urb(instance->rcv_urb, usb_dev, usb_rcvintpipe(usb_dev, CXACRU_EP_CMD), instance->rcv_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->rcv_done, 1); - usb_fill_int_urb(instance->snd_urb, + usb_fill_int_urb(instance->snd_urb, usb_dev, usb_sndintpipe(usb_dev, CXACRU_EP_CMD), instance->snd_buf, PAGE_SIZE, cxacru_blocking_completion, &instance->snd_done, 4); + } else { + usb_fill_bulk_urb(instance->rcv_urb, + usb_dev, usb_rcvbulkpipe(usb_dev, CXACRU_EP_CMD), + instance->rcv_buf, PAGE_SIZE, + cxacru_blocking_completion, &instance->rcv_done); + + usb_fill_bulk_urb(instance->snd_urb, + usb_dev, usb_sndbulkpipe(usb_dev, CXACRU_EP_CMD), + instance->snd_buf, PAGE_SIZE, + cxacru_blocking_completion, &instance->snd_done); + } mutex_init(&instance->cm_serialize); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 1833b3a71515..bc62fae0680f 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -965,7 +965,8 @@ static int acm_probe(struct usb_interface *intf, } if (!buflen) { - if (intf->cur_altsetting->endpoint->extralen && + if (intf->cur_altsetting->endpoint && + intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { dev_dbg(&intf->dev, "Seeking extra descriptors on endpoint\n"); @@ -1481,6 +1482,11 @@ static int acm_reset_resume(struct usb_interface *intf) USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ USB_CDC_ACM_PROTO_VENDOR) +#define SAMSUNG_PCSUITE_ACM_INFO(x) \ + USB_DEVICE_AND_INTERFACE_INFO(0x04e7, x, \ + USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, \ + USB_CDC_ACM_PROTO_VENDOR) + /* * USB driver structure. */ @@ -1591,6 +1597,17 @@ static const struct usb_device_id acm_ids[] = { { NOKIA_PCSUITE_ACM_INFO(0x0108), }, /* Nokia 5320 XpressMusic 2G */ { NOKIA_PCSUITE_ACM_INFO(0x01f5), }, /* Nokia N97, RM-505 */ { NOKIA_PCSUITE_ACM_INFO(0x02e3), }, /* Nokia 5230, RM-588 */ + { NOKIA_PCSUITE_ACM_INFO(0x0178), }, /* Nokia E63 */ + { NOKIA_PCSUITE_ACM_INFO(0x010e), }, /* Nokia E75 */ + { NOKIA_PCSUITE_ACM_INFO(0x02d9), }, /* Nokia 6760 Slide */ + { NOKIA_PCSUITE_ACM_INFO(0x01d0), }, /* Nokia E52 */ + { NOKIA_PCSUITE_ACM_INFO(0x0223), }, /* Nokia E72 */ + { NOKIA_PCSUITE_ACM_INFO(0x0275), }, /* Nokia X6 */ + { NOKIA_PCSUITE_ACM_INFO(0x026c), }, /* Nokia N97 Mini */ + { NOKIA_PCSUITE_ACM_INFO(0x0154), }, /* Nokia 5800 XpressMusic */ + { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ + { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ + { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ @@ -1599,6 +1616,10 @@ static const struct usb_device_id acm_ids[] = { .driver_info = NOT_A_MODEM, }, + /* control interfaces without any protocol set */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTO_NONE) }, + /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_V25TER) }, diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 7e594449600e..9eed5b52d9de 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -91,12 +91,12 @@ config USB_DYNAMIC_MINORS If you are unsure about this, say N here. config USB_SUSPEND - bool "USB runtime power management (suspend/resume and wakeup)" + bool "USB runtime power management (autosuspend) and wakeup" depends on USB && PM_RUNTIME help If you say Y here, you can use driver calls or the sysfs - "power/level" file to suspend or resume individual USB - peripherals and to enable or disable autosuspend (see + "power/control" file to enable or disable autosuspend for + individual USB peripherals (see Documentation/usb/power-management.txt for more details). Also, USB "remote wakeup" signaling is supported, whereby some diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index f06f5dbc8cdc..1e6ccef2cf0c 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -159,9 +159,9 @@ void usb_major_cleanup(void) int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver) { - int retval = -EINVAL; + int retval; int minor_base = class_driver->minor_base; - int minor = 0; + int minor; char name[20]; char *temp; @@ -173,12 +173,17 @@ int usb_register_dev(struct usb_interface *intf, */ minor_base = 0; #endif - intf->minor = -1; - - dbg ("looking for a minor, starting at %d", minor_base); if (class_driver->fops == NULL) - goto exit; + return -EINVAL; + if (intf->minor >= 0) + return -EADDRINUSE; + + retval = init_usb_class(); + if (retval) + return retval; + + dev_dbg(&intf->dev, "looking for a minor, starting at %d", minor_base); down_write(&minor_rwsem); for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { @@ -186,20 +191,12 @@ int usb_register_dev(struct usb_interface *intf, continue; usb_minors[minor] = class_driver->fops; - - retval = 0; + intf->minor = minor; break; } up_write(&minor_rwsem); - - if (retval) - goto exit; - - retval = init_usb_class(); - if (retval) - goto exit; - - intf->minor = minor; + if (intf->minor < 0) + return -EXFULL; /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); @@ -213,11 +210,11 @@ int usb_register_dev(struct usb_interface *intf, "%s", temp); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); - usb_minors[intf->minor] = NULL; + usb_minors[minor] = NULL; + intf->minor = -1; up_write(&minor_rwsem); retval = PTR_ERR(intf->usb_dev); } -exit: return retval; } EXPORT_SYMBOL_GPL(usb_register_dev); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fd4c36ea5e46..9f0ce7de0e36 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1724,6 +1724,15 @@ free_interfaces: if (ret) goto free_interfaces; + /* if it's already configured, clear out old state first. + * getting rid of old interfaces means unbinding their drivers. + */ + if (dev->state != USB_STATE_ADDRESS) + usb_disable_device(dev, 1); /* Skip ep0 */ + + /* Get rid of pending async Set-Config requests for this device */ + cancel_async_set_config(dev); + /* Make sure we have bandwidth (and available HCD resources) for this * configuration. Remove endpoints from the schedule if we're dropping * this configuration to set configuration 0. After this point, the @@ -1733,20 +1742,11 @@ free_interfaces: mutex_lock(&hcd->bandwidth_mutex); ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); if (ret < 0) { - usb_autosuspend_device(dev); mutex_unlock(&hcd->bandwidth_mutex); + usb_autosuspend_device(dev); goto free_interfaces; } - /* if it's already configured, clear out old state first. - * getting rid of old interfaces means unbinding their drivers. - */ - if (dev->state != USB_STATE_ADDRESS) - usb_disable_device(dev, 1); /* Skip ep0 */ - - /* Get rid of pending async Set-Config requests for this device */ - cancel_async_set_config(dev); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -1761,8 +1761,8 @@ free_interfaces: if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); - usb_autosuspend_device(dev); mutex_unlock(&hcd->bandwidth_mutex); + usb_autosuspend_device(dev); goto free_interfaces; } mutex_unlock(&hcd->bandwidth_mutex); @@ -1802,6 +1802,7 @@ free_interfaces: intf->dev.groups = usb_interface_groups; intf->dev.dma_mask = dev->dev.dma_mask; INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); + intf->minor = -1; device_initialize(&intf->dev); dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index e483f80822d2..1160c55de7f2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -723,12 +723,12 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) /** * usb_string_ids_n() - allocate unused string IDs in batch - * @cdev: the device whose string descriptor IDs are being allocated + * @c: the device whose string descriptor IDs are being allocated * @n: number of string IDs to allocate * Context: single threaded during gadget setup * * Returns the first requested ID. This ID and next @n-1 IDs are now - * valid IDs. At least providind that @n is non zore because if it + * valid IDs. At least provided that @n is non-zero because if it * is, returns last requested ID which is now very useful information. * * @usb_string_ids_n() is called from bind() callbacks to allocate diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 166bf71fd348..e03058fe23cb 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1609,6 +1609,7 @@ static int __init m66592_probe(struct platform_device *pdev) /* initialize ucd */ m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL); if (m66592 == NULL) { + ret = -ENOMEM; pr_err("kzalloc error\n"); goto clean_up; } diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 70a817842755..2456ccd9965e 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1557,6 +1557,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) /* initialize ucd */ r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL); if (r8a66597 == NULL) { + ret = -ENOMEM; printk(KERN_ERR "kzalloc error\n"); goto clean_up; } diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 020fa5a25fda..972d5ddd1e18 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -293,9 +293,13 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, /* mandatory */ case OID_GEN_VENDOR_DESCRIPTION: pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__); - length = strlen (rndis_per_dev_params [configNr].vendorDescr); - memcpy (outbuf, - rndis_per_dev_params [configNr].vendorDescr, length); + if ( rndis_per_dev_params [configNr].vendorDescr ) { + length = strlen (rndis_per_dev_params [configNr].vendorDescr); + memcpy (outbuf, + rndis_per_dev_params [configNr].vendorDescr, length); + } else { + outbuf[0] = 0; + } retval = 0; break; @@ -1148,7 +1152,7 @@ static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; #endif /* CONFIG_USB_GADGET_DEBUG_FILES */ -int __init rndis_init (void) +int rndis_init(void) { u8 i; diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index c236aaa9dcd1..907c33008118 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h @@ -262,7 +262,7 @@ int rndis_signal_disconnect (int configNr); int rndis_state (int configNr); extern void rndis_set_host_mac (int configNr, const u8 *addr); -int __devinit rndis_init (void); +int rndis_init(void); void rndis_exit (void); #endif /* _LINUX_RNDIS_H */ diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 521ebed0118d..a229744a8c7d 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -12,8 +12,6 @@ * published by the Free Software Foundation. */ -#define DEBUG - #include <linux/kernel.h> #include <linux/module.h> #include <linux/spinlock.h> diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index 2dcffdac86d2..5e807f083bc8 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -94,7 +94,7 @@ uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt) break; } - if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) { + if (i == ARRAY_SIZE(uvc_formats)) { printk(KERN_INFO "Unsupported format 0x%08x.\n", fmt->fmt.pix.pixelformat); return -EINVAL; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 58b72d741d93..a1e8d273103f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -119,6 +119,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci->broken_periodic = 1; ehci_info(ehci, "using broken periodic workaround\n"); } + if (pdev->device == 0x0806 || pdev->device == 0x0811 + || pdev->device == 0x0829) { + ehci_info(ehci, "disable lpm for langwell/penwell\n"); + ehci->has_lpm = 0; + } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 335ee699fd85..ba52be473027 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -192,17 +192,19 @@ ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *mat } rv = usb_add_hcd(hcd, irq, 0); - if (rv == 0) - return 0; + if (rv) + goto err_ehci; + + return 0; +err_ehci: + if (ehci->has_amcc_usb23) + iounmap(ehci->ohci_hcctrl_reg); iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - - if (ehci->has_amcc_usb23) - iounmap(ehci->ohci_hcctrl_reg); err_rmr: usb_put_hcd(hcd); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index d1a3dfc9a408..bdba8c5d844a 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -829,6 +829,7 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, * almost immediately. With ISP1761, this register requires a delay of * 195ns between a write and subsequent read (see section 15.1.1.3). */ + mmiowb(); ndelay(195); skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG); @@ -870,6 +871,7 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, * almost immediately. With ISP1761, this register requires a delay of * 195ns between a write and subsequent read (see section 15.1.1.3). */ + mmiowb(); ndelay(195); skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index bc3f4f427065..48e60d166ff0 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -131,7 +131,7 @@ static void next_trb(struct xhci_hcd *xhci, *seg = (*seg)->next; *trb = ((*seg)->trbs); } else { - *trb = (*trb)++; + (*trb)++; } } @@ -1551,6 +1551,10 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, /* calc actual length */ if (ep->skip) { td->urb->iso_frame_desc[idx].actual_length = 0; + /* Update ring dequeue pointer */ + while (ep_ring->dequeue != td->last_trb) + inc_deq(xhci, ep_ring, false); + inc_deq(xhci, ep_ring, false); return finish_td(xhci, td, event_trb, event, ep, status, true); } diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index d240de097c62..801324af9470 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -439,7 +439,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* drain secondary buffer */ int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary; i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount); - if (i < 0) { + if (i) { retval = -EFAULT; goto exit; } diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 2de49c8887c5..bc88c79875a1 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -542,7 +542,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, retval = io_res; else { io_res = copy_to_user(user_buffer, buffer, dev->report_size); - if (io_res < 0) + if (io_res) retval = -EFAULT; } break; @@ -574,7 +574,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, } io_res = copy_to_user((struct iowarrior_info __user *)arg, &info, sizeof(struct iowarrior_info)); - if (io_res < 0) + if (io_res) retval = -EFAULT; break; } diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 59dc3d351b60..5ab5bb89bae3 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -322,6 +322,7 @@ cppi_channel_allocate(struct dma_controller *c, index, transmit ? 'T' : 'R', cppi_ch); cppi_ch->hw_ep = ep; cppi_ch->channel.status = MUSB_DMA_STATUS_FREE; + cppi_ch->channel.max_len = 0x7fffffff; DBG(4, "Allocate CPPI%d %cX\n", index, transmit ? 'T' : 'R'); return &cppi_ch->channel; diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index c79a5e30d437..9e8639d4e862 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -195,15 +195,14 @@ static const struct file_operations musb_regdump_fops = { static int musb_test_mode_open(struct inode *inode, struct file *file) { - file->private_data = inode->i_private; - return single_open(file, musb_test_mode_show, inode->i_private); } static ssize_t musb_test_mode_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { - struct musb *musb = file->private_data; + struct seq_file *s = file->private_data; + struct musb *musb = s->private; u8 test = 0; char buf[18]; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6fca870e957e..d065e23f123e 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -300,6 +300,11 @@ static void txstate(struct musb *musb, struct musb_request *req) #ifndef CONFIG_MUSB_PIO_ONLY if (is_dma_capable() && musb_ep->dma) { struct dma_controller *c = musb->dma_controller; + size_t request_size; + + /* setup DMA, then program endpoint CSR */ + request_size = min_t(size_t, request->length - request->actual, + musb_ep->dma->max_len); use_dma = (request->dma != DMA_ADDR_INVALID); @@ -307,11 +312,6 @@ static void txstate(struct musb *musb, struct musb_request *req) #ifdef CONFIG_USB_INVENTRA_DMA { - size_t request_size; - - /* setup DMA, then program endpoint CSR */ - request_size = min_t(size_t, request->length, - musb_ep->dma->max_len); if (request_size < musb_ep->packet_sz) musb_ep->dma->desired_mode = 0; else @@ -373,8 +373,8 @@ static void txstate(struct musb *musb, struct musb_request *req) use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, 0, - request->dma, - request->length); + request->dma + request->actual, + request_size); if (!use_dma) { c->channel_release(musb_ep->dma); musb_ep->dma = NULL; @@ -386,8 +386,8 @@ static void txstate(struct musb *musb, struct musb_request *req) use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, request->zero, - request->dma, - request->length); + request->dma + request->actual, + request_size); #endif } #endif @@ -501,26 +501,14 @@ void musb_g_tx(struct musb *musb, u8 epnum) request->zero = 0; } - /* ... or if not, then complete it. */ - musb_g_giveback(musb_ep, request, 0); - - /* - * Kickstart next transfer if appropriate; - * the packet that just completed might not - * be transmitted for hours or days. - * REVISIT for double buffering... - * FIXME revisit for stalls too... - */ - musb_ep_select(mbase, epnum); - csr = musb_readw(epio, MUSB_TXCSR); - if (csr & MUSB_TXCSR_FIFONOTEMPTY) - return; - - request = musb_ep->desc ? next_request(musb_ep) : NULL; - if (!request) { - DBG(4, "%s idle now\n", - musb_ep->end_point.name); - return; + if (request->actual == request->length) { + musb_g_giveback(musb_ep, request, 0); + request = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!request) { + DBG(4, "%s idle now\n", + musb_ep->end_point.name); + return; + } } } @@ -568,11 +556,19 @@ static void rxstate(struct musb *musb, struct musb_request *req) { const u8 epnum = req->epnum; struct usb_request *request = &req->request; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; + struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; unsigned fifo_count = 0; - u16 len = musb_ep->packet_sz; + u16 len; u16 csr = musb_readw(epio, MUSB_RXCSR); + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + if (hw_ep->is_shared_fifo) + musb_ep = &hw_ep->ep_in; + else + musb_ep = &hw_ep->ep_out; + + len = musb_ep->packet_sz; /* We shouldn't get here while DMA is active, but we do... */ if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { @@ -647,8 +643,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) */ csr |= MUSB_RXCSR_DMAENAB; -#ifdef USE_MODE1 csr |= MUSB_RXCSR_AUTOCLEAR; +#ifdef USE_MODE1 /* csr |= MUSB_RXCSR_DMAMODE; */ /* this special sequence (enabling and then @@ -663,10 +659,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (request->actual < request->length) { int transfer_size = 0; #ifdef USE_MODE1 - transfer_size = min(request->length, + transfer_size = min(request->length - request->actual, channel->max_len); #else - transfer_size = len; + transfer_size = min(request->length - request->actual, + (unsigned)len); #endif if (transfer_size <= musb_ep->packet_sz) musb_ep->dma->desired_mode = 0; @@ -740,9 +737,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) u16 csr; struct usb_request *request; void __iomem *mbase = musb->mregs; - struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; + struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; struct dma_channel *dma; + struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; + + if (hw_ep->is_shared_fifo) + musb_ep = &hw_ep->ep_in; + else + musb_ep = &hw_ep->ep_out; musb_ep_select(mbase, epnum); @@ -1081,7 +1084,7 @@ struct free_record { /* * Context: controller locked, IRQs blocked. */ -static void musb_ep_restart(struct musb *musb, struct musb_request *req) +void musb_ep_restart(struct musb *musb, struct musb_request *req) { DBG(3, "<== %s request %p len %u on hw_ep%d\n", req->tx ? "TX/IN" : "RX/OUT", diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index c8b140325d82..572b1da7f2dc 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -105,4 +105,6 @@ extern void musb_gadget_cleanup(struct musb *); extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); +extern void musb_ep_restart(struct musb *, struct musb_request *); + #endif /* __MUSB_GADGET_H */ diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 59bef8f3a358..6dd03f4c5f49 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -261,6 +261,7 @@ __acquires(musb->lock) ctrlrequest->wIndex & 0x0f; struct musb_ep *musb_ep; struct musb_hw_ep *ep; + struct musb_request *request; void __iomem *regs; int is_in; u16 csr; @@ -302,6 +303,14 @@ __acquires(musb->lock) musb_writew(regs, MUSB_RXCSR, csr); } + /* Maybe start the first request in the queue */ + request = to_musb_request( + next_request(musb_ep)); + if (!musb_ep->busy && request) { + DBG(3, "restarting the request\n"); + musb_ep_restart(musb, request); + } + /* select ep0 again */ musb_ep_select(mbase, 0); } break; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 877d20b1dff9..9e65c47cc98b 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -660,6 +660,12 @@ static bool musb_tx_dma_program(struct dma_controller *dma, qh->segsize = length; + /* + * Ensure the data reaches to main memory before starting + * DMA transfer + */ + wmb(); + if (!dma->channel_program(channel, pkt_size, mode, urb->transfer_dma + offset, length)) { dma->channel_release(channel); diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 0e8888588d4e..0bc97698af15 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -347,11 +347,20 @@ static void twl4030_i2c_access(struct twl4030_usb *twl, int on) } } -static void twl4030_phy_power(struct twl4030_usb *twl, int on) +static void __twl4030_phy_power(struct twl4030_usb *twl, int on) { - u8 pwr; + u8 pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); + + if (on) + pwr &= ~PHY_PWR_PHYPWD; + else + pwr |= PHY_PWR_PHYPWD; - pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); + WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); +} + +static void twl4030_phy_power(struct twl4030_usb *twl, int on) +{ if (on) { regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); @@ -365,15 +374,13 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); - pwr &= ~PHY_PWR_PHYPWD; - WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + __twl4030_phy_power(twl, 1); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); - } else { - pwr |= PHY_PWR_PHYPWD; - WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + } else { + __twl4030_phy_power(twl, 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); regulator_disable(twl->usb3v1); @@ -387,19 +394,25 @@ static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off) twl4030_phy_power(twl, 0); twl->asleep = 1; + dev_dbg(twl->dev, "%s\n", __func__); } -static void twl4030_phy_resume(struct twl4030_usb *twl) +static void __twl4030_phy_resume(struct twl4030_usb *twl) { - if (!twl->asleep) - return; - twl4030_phy_power(twl, 1); twl4030_i2c_access(twl, 1); twl4030_usb_set_mode(twl, twl->usb_mode); if (twl->usb_mode == T2_USB_MODE_ULPI) twl4030_i2c_access(twl, 0); +} + +static void twl4030_phy_resume(struct twl4030_usb *twl) +{ + if (!twl->asleep) + return; + __twl4030_phy_resume(twl); twl->asleep = 0; + dev_dbg(twl->dev, "%s\n", __func__); } static int twl4030_usb_ldo_init(struct twl4030_usb *twl) @@ -408,8 +421,8 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); - /* put VUSB3V1 LDO in active state */ - twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); + /* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/ + /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/ /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); @@ -502,6 +515,26 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) return IRQ_HANDLED; } +static void twl4030_usb_phy_init(struct twl4030_usb *twl) +{ + int status; + + status = twl4030_usb_linkstat(twl); + if (status >= 0) { + if (status == USB_EVENT_NONE) { + __twl4030_phy_power(twl, 0); + twl->asleep = 1; + } else { + __twl4030_phy_resume(twl); + twl->asleep = 0; + } + + blocking_notifier_call_chain(&twl->otg.notifier, status, + twl->otg.gadget); + } + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); +} + static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) { struct twl4030_usb *twl = xceiv_to_twl(x); @@ -568,7 +601,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) twl->otg.set_peripheral = twl4030_set_peripheral; twl->otg.set_suspend = twl4030_set_suspend; twl->usb_mode = pdata->usb_mode; - twl->asleep = 1; + twl->asleep = 1; /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -606,15 +639,10 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) return status; } - /* The IRQ handler just handles changes from the previous states - * of the ID and VBUS pins ... in probe() we must initialize that - * previous state. The easy way: fake an IRQ. - * - * REVISIT: a real IRQ might have happened already, if PREEMPT is - * enabled. Else the IRQ may not yet be configured or enabled, - * because of scheduling delays. + /* Power down phy or make it work according to + * current link state. */ - twl4030_usb_irq(twl->irq, twl); + twl4030_usb_phy_init(twl); dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); return 0; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2bef4415c19c..4f1744c5871f 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -56,6 +56,7 @@ static int debug; static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ @@ -88,6 +89,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ @@ -109,6 +111,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ + { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ @@ -122,14 +125,14 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ - { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ - { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ - { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ - { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ { USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */ { USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */ + { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ + { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; @@ -222,8 +225,8 @@ static struct usb_serial_driver cp210x_device = { #define BITS_STOP_2 0x0002 /* CP210X_SET_BREAK */ -#define BREAK_ON 0x0000 -#define BREAK_OFF 0x0001 +#define BREAK_ON 0x0001 +#define BREAK_OFF 0x0000 /* CP210X_(SET_MHS|GET_MDMSTS) */ #define CONTROL_DTR 0x0001 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index eb12d9b096b4..97cc87d654ce 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -180,6 +180,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, + { USB_DEVICE(FTDI_VID, FTDI_LENZ_LIUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, @@ -750,6 +751,16 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XVERVE_SIGNALYZER_SH4_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, SEGWAY_RMP200_PID) }, + { USB_DEVICE(IONICS_VID, IONICS_PLUGCOMPUTER_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_24_MASTER_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_PC_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_USB_DMX_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MIDI_TIMECODE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MINI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MAXI_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_MEDIA_WING_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CHAMSYS_WING_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -1376,7 +1387,7 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port) } /* set max packet size based on descriptor */ - priv->max_packet_size = ep_desc->wMaxPacketSize; + priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize); dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); } @@ -1831,7 +1842,7 @@ static int ftdi_process_packet(struct tty_struct *tty, if (port->port.console && port->sysrq) { for (i = 0; i < len; i++, ch++) { - if (!usb_serial_handle_sysrq_char(tty, port, *ch)) + if (!usb_serial_handle_sysrq_char(port, *ch)) tty_insert_flip_char(tty, *ch, flag); } } else { diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 6e612c52e763..15a4583775ad 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -110,6 +110,9 @@ /* Propox devices */ #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 +/* Lenz LI-USB Computer Interface. */ +#define FTDI_LENZ_LIUSB_PID 0xD780 + /* * Xsens Technologies BV products (http://www.xsens.com). */ @@ -132,6 +135,18 @@ #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ /* + * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs + */ +#define FTDI_CHAMSYS_24_MASTER_WING_PID 0xDAF8 +#define FTDI_CHAMSYS_PC_WING_PID 0xDAF9 +#define FTDI_CHAMSYS_USB_DMX_PID 0xDAFA +#define FTDI_CHAMSYS_MIDI_TIMECODE_PID 0xDAFB +#define FTDI_CHAMSYS_MINI_WING_PID 0xDAFC +#define FTDI_CHAMSYS_MAXI_WING_PID 0xDAFD +#define FTDI_CHAMSYS_MEDIA_WING_PID 0xDAFE +#define FTDI_CHAMSYS_WING_PID 0xDAFF + +/* * Westrex International devices submitted by Cory Lee */ #define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ @@ -989,6 +1004,12 @@ #define ALTI2_N3_PID 0x6001 /* Neptune 3 */ /* + * Ionics PlugComputer + */ +#define IONICS_VID 0x1c0c +#define IONICS_PLUGCOMPUTER_PID 0x0102 + +/* * Dresden Elektronik Sensor Terminal Board */ #define DE_VID 0x1cf1 /* Vendor ID */ diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index ca92f67747cc..e6833e216fc9 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -343,7 +343,7 @@ void usb_serial_generic_process_read_urb(struct urb *urb) tty_insert_flip_string(tty, ch, urb->actual_length); else { for (i = 0; i < urb->actual_length; i++, ch++) { - if (!usb_serial_handle_sysrq_char(tty, port, *ch)) + if (!usb_serial_handle_sysrq_char(port, *ch)) tty_insert_flip_char(tty, *ch, TTY_NORMAL); } } @@ -448,12 +448,11 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle); #ifdef CONFIG_MAGIC_SYSRQ -int usb_serial_handle_sysrq_char(struct tty_struct *tty, - struct usb_serial_port *port, unsigned int ch) +int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) { if (port->sysrq && port->port.console) { if (ch && time_before(jiffies, port->sysrq)) { - handle_sysrq(ch, tty); + handle_sysrq(ch); port->sysrq = 0; return 1; } @@ -462,8 +461,7 @@ int usb_serial_handle_sysrq_char(struct tty_struct *tty, return 0; } #else -int usb_serial_handle_sysrq_char(struct tty_struct *tty, - struct usb_serial_port *port, unsigned int ch) +int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) { return 0; } @@ -518,6 +516,7 @@ void usb_serial_generic_disconnect(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) generic_cleanup(serial->port[i]); } +EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect); void usb_serial_generic_release(struct usb_serial *serial) { diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index dc47f986df57..a7cfc5952937 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1151,7 +1151,7 @@ static int download_fw(struct edgeport_serial *serial) /* Check if we have an old version in the I2C and update if necessary */ - if (download_cur_ver != download_new_ver) { + if (download_cur_ver < download_new_ver) { dbg("%s - Update I2C dld from %d.%d to %d.%d", __func__, firmware_version->Ver_Major, @@ -1284,7 +1284,7 @@ static int download_fw(struct edgeport_serial *serial) kfree(header); kfree(rom_desc); kfree(ti_manuf_desc); - return status; + return -EINVAL; } /* Update I2C with type 0xf2 record with correct diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 30922a7e3347..aa665817a272 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -2024,6 +2024,9 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file, case TIOCGICOUNT: cnow = mos7720_port->icount; + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 585b7e663740..1a42bc213799 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -119,16 +119,20 @@ * by making a change here, in moschip_port_id_table, and in * moschip_id_table_combined */ -#define USB_VENDOR_ID_BANDB 0x0856 -#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 -#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 -#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 -#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 -#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 -#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 -#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 -#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 -#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 +#define USB_VENDOR_ID_BANDB 0x0856 +#define BANDB_DEVICE_ID_USO9ML2_2 0xAC22 +#define BANDB_DEVICE_ID_USO9ML2_2P 0xBC00 +#define BANDB_DEVICE_ID_USO9ML2_4 0xAC24 +#define BANDB_DEVICE_ID_USO9ML2_4P 0xBC01 +#define BANDB_DEVICE_ID_US9ML2_2 0xAC29 +#define BANDB_DEVICE_ID_US9ML2_4 0xAC30 +#define BANDB_DEVICE_ID_USPTL4_2 0xAC31 +#define BANDB_DEVICE_ID_USPTL4_4 0xAC32 +#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 +#define BANDB_DEVICE_ID_USOPTL4_2P 0xBC02 +#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USOPTL4_4P 0xBC03 +#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -184,13 +188,17 @@ static const struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, @@ -201,13 +209,17 @@ static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_US9ML2_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4P)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, @@ -2273,6 +2285,9 @@ static int mos7840_ioctl(struct tty_struct *tty, struct file *file, case TIOCGICOUNT: cnow = mos7840_port->icount; smp_rmb(); + + memset(&icount, 0, sizeof(struct serial_icounter_struct)); + icount.cts = cnow.cts; icount.dsr = cnow.dsr; icount.rng = cnow.rng; diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index a6b207c84917..1f00f243c26c 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -25,6 +25,7 @@ static int debug; static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */ + { USB_DEVICE(0x0df7, 0x0900) }, /* Mobile Action i-gotU */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9fc6ea2c681f..c46911af282f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -164,6 +164,14 @@ static void option_instat_callback(struct urb *urb); #define YISO_VENDOR_ID 0x0EAB #define YISO_PRODUCT_U893 0xC893 +/* + * NOVATEL WIRELESS PRODUCTS + * + * Note from Novatel Wireless: + * If your Novatel modem does not work on linux, don't + * change the option module, but check our website. If + * that does not help, contact ddeschepper@nvtl.com +*/ /* MERLIN EVDO PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_V640 0x1100 #define NOVATELWIRELESS_PRODUCT_V620 0x1110 @@ -185,24 +193,39 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EU730 0x2400 #define NOVATELWIRELESS_PRODUCT_EU740 0x2410 #define NOVATELWIRELESS_PRODUCT_EU870D 0x2420 - /* OVATION PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 -#define NOVATELWIRELESS_PRODUCT_U727 0x5010 -#define NOVATELWIRELESS_PRODUCT_MC727_NEW 0x5100 -#define NOVATELWIRELESS_PRODUCT_MC760 0x6000 +/* + * Note from Novatel Wireless: + * All PID in the 5xxx range are currently reserved for + * auto-install CDROMs, and should not be added to this + * module. + * + * #define NOVATELWIRELESS_PRODUCT_U727 0x5010 + * #define NOVATELWIRELESS_PRODUCT_MC727_NEW 0x5100 +*/ #define NOVATELWIRELESS_PRODUCT_OVMC760 0x6002 - -/* FUTURE NOVATEL PRODUCTS */ -#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001 -#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED 0X7000 -#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED 0X7001 -#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED 0X8000 -#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0X8001 -#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0X9000 -#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0X9001 -#define NOVATELWIRELESS_PRODUCT_GLOBAL 0XA001 +#define NOVATELWIRELESS_PRODUCT_MC780 0x6010 +#define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0x6000 +#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0x6001 +#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED 0x7000 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED 0x7001 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3 0x7003 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4 0x7004 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5 0x7005 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED6 0x7006 +#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED7 0x7007 +#define NOVATELWIRELESS_PRODUCT_MC996D 0x7030 +#define NOVATELWIRELESS_PRODUCT_MF3470 0x7041 +#define NOVATELWIRELESS_PRODUCT_MC547 0x7042 +#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED 0x8000 +#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 +#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 +#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_G1 0xA001 +#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 +#define NOVATELWIRELESS_PRODUCT_G2 0xA010 /* AMOI PRODUCTS */ #define AMOI_VENDOR_ID 0x1614 @@ -365,6 +388,10 @@ static void option_instat_callback(struct urb *urb); #define OLIVETTI_VENDOR_ID 0x0b3c #define OLIVETTI_PRODUCT_OLICARD100 0xc000 +/* Celot products */ +#define CELOT_VENDOR_ID 0x211f +#define CELOT_PRODUCT_CT680M 0x6801 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -486,36 +513,44 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, /* Novatel Merlin ES620 SM Bus */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, /* Novatel EVDO product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, /* Novatel HSPA product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, /* Novatel EVDO Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, /* Novatel HSPA Embedded product */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL) }, /* Novatel Global product */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC780) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED6) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED7) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC996D) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MF3470) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -887,10 +922,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, - { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, - { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, + { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 6b6001822279..8ae4c6cbc38a 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -86,6 +86,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, + { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, @@ -788,7 +789,7 @@ static void pl2303_process_read_urb(struct urb *urb) if (port->port.console && port->sysrq) { for (i = 0; i < urb->actual_length; ++i) - if (!usb_serial_handle_sysrq_char(tty, port, data[i])) + if (!usb_serial_handle_sysrq_char(port, data[i])) tty_insert_flip_char(tty, data[i], tty_flag); } else { tty_insert_flip_string_fixed_flag(tty, data, tty_flag, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index a871645389dd..43eb9bdad422 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -128,6 +128,10 @@ #define CRESSI_VENDOR_ID 0x04b8 #define CRESSI_EDY_PRODUCT_ID 0x0521 +/* Zeagle dive computer interface */ +#define ZEAGLE_VENDOR_ID 0x04b8 +#define ZEAGLE_N2ITION3_PRODUCT_ID 0x0522 + /* Sony, USB data cable for CMD-Jxx mobile phones */ #define SONY_VENDOR_ID 0x054c #define SONY_QN3USB_PRODUCT_ID 0x0437 diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 6e82d4f54bc8..e986002b3844 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -15,6 +15,7 @@ #include <linux/serial.h> #include <linux/usb.h> #include <linux/usb/serial.h> +#include <linux/serial_reg.h> #include <linux/uaccess.h> #define QT_OPEN_CLOSE_CHANNEL 0xca @@ -27,36 +28,11 @@ #define QT_HW_FLOW_CONTROL_MASK 0xc5 #define QT_SW_FLOW_CONTROL_MASK 0xc6 -#define MODEM_CTL_REGISTER 0x04 -#define MODEM_STATUS_REGISTER 0x06 - - -#define SERIAL_LSR_OE 0x02 -#define SERIAL_LSR_PE 0x04 -#define SERIAL_LSR_FE 0x08 -#define SERIAL_LSR_BI 0x10 - -#define SERIAL_LSR_TEMT 0x40 - -#define SERIAL_MCR_DTR 0x01 -#define SERIAL_MCR_RTS 0x02 -#define SERIAL_MCR_LOOP 0x10 - -#define SERIAL_MSR_CTS 0x10 -#define SERIAL_MSR_CD 0x80 -#define SERIAL_MSR_RI 0x40 -#define SERIAL_MSR_DSR 0x20 #define SERIAL_MSR_MASK 0xf0 -#define SERIAL_CRTSCTS ((SERIAL_MCR_RTS << 8) | SERIAL_MSR_CTS) +#define SERIAL_CRTSCTS ((UART_MCR_RTS << 8) | UART_MSR_CTS) -#define SERIAL_8_DATA 0x03 -#define SERIAL_7_DATA 0x02 -#define SERIAL_6_DATA 0x01 -#define SERIAL_5_DATA 0x00 - -#define SERIAL_ODD_PARITY 0X08 -#define SERIAL_EVEN_PARITY 0X18 +#define SERIAL_EVEN_PARITY (UART_LCR_PARITY | UART_LCR_EPAR) #define MAX_BAUD_RATE 460800 @@ -70,7 +46,7 @@ #define FULLPWRBIT 0x00000080 #define NEXT_BOARD_POWER_BIT 0x00000004 -static int debug = 1; +static int debug; /* Version Information */ #define DRIVER_VERSION "v0.1" @@ -99,10 +75,12 @@ static struct usb_driver ssu100_driver = { }; struct ssu100_port_private { + spinlock_t status_lock; u8 shadowLSR; u8 shadowMSR; wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ unsigned short max_packet_size; + struct async_icount icount; }; static void ssu100_release(struct usb_serial *serial) @@ -150,9 +128,10 @@ static inline int ssu100_getregister(struct usb_device *dev, static inline int ssu100_setregister(struct usb_device *dev, unsigned short uart, + unsigned short reg, u16 data) { - u16 value = (data << 8) | MODEM_CTL_REGISTER; + u16 value = (data << 8) | reg; return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), QT_SET_GET_REGISTER, 0x40, value, uart, @@ -178,11 +157,11 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set, clear &= ~set; /* 'set' takes precedence over 'clear' */ urb_value = 0; if (set & TIOCM_DTR) - urb_value |= SERIAL_MCR_DTR; + urb_value |= UART_MCR_DTR; if (set & TIOCM_RTS) - urb_value |= SERIAL_MCR_RTS; + urb_value |= UART_MCR_RTS; - result = ssu100_setregister(dev, 0, urb_value); + result = ssu100_setregister(dev, 0, UART_MCR, urb_value); if (result < 0) dbg("%s Error from MODEM_CTRL urb", __func__); @@ -264,24 +243,24 @@ static void ssu100_set_termios(struct tty_struct *tty, if (cflag & PARENB) { if (cflag & PARODD) - urb_value |= SERIAL_ODD_PARITY; + urb_value |= UART_LCR_PARITY; else urb_value |= SERIAL_EVEN_PARITY; } switch (cflag & CSIZE) { case CS5: - urb_value |= SERIAL_5_DATA; + urb_value |= UART_LCR_WLEN5; break; case CS6: - urb_value |= SERIAL_6_DATA; + urb_value |= UART_LCR_WLEN6; break; case CS7: - urb_value |= SERIAL_7_DATA; + urb_value |= UART_LCR_WLEN7; break; default: case CS8: - urb_value |= SERIAL_8_DATA; + urb_value |= UART_LCR_WLEN8; break; } @@ -333,6 +312,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) struct ssu100_port_private *priv = usb_get_serial_port_data(port); u8 *data; int result; + unsigned long flags; dbg("%s - port %d", __func__, port->number); @@ -350,11 +330,10 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } - priv->shadowLSR = data[0] & (SERIAL_LSR_OE | SERIAL_LSR_PE | - SERIAL_LSR_FE | SERIAL_LSR_BI); - - priv->shadowMSR = data[1] & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | - SERIAL_MSR_RI | SERIAL_MSR_CD); + spin_lock_irqsave(&priv->status_lock, flags); + priv->shadowLSR = data[0]; + priv->shadowMSR = data[1]; + spin_unlock_irqrestore(&priv->status_lock, flags); kfree(data); @@ -398,11 +377,51 @@ static int get_serial_info(struct usb_serial_port *port, return 0; } +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct ssu100_port_private *priv = usb_get_serial_port_data(port); + struct async_icount prev, cur; + unsigned long flags; + + spin_lock_irqsave(&priv->status_lock, flags); + prev = priv->icount; + spin_unlock_irqrestore(&priv->status_lock, flags); + + while (1) { + wait_event_interruptible(priv->delta_msr_wait, + ((priv->icount.rng != prev.rng) || + (priv->icount.dsr != prev.dsr) || + (priv->icount.dcd != prev.dcd) || + (priv->icount.cts != prev.cts))); + + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave(&priv->status_lock, flags); + cur = priv->icount; + spin_unlock_irqrestore(&priv->status_lock, flags); + + if ((prev.rng == cur.rng) && + (prev.dsr == cur.dsr) && + (prev.dcd == cur.dcd) && + (prev.cts == cur.cts)) + return -EIO; + + if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) || + (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) || + (arg & TIOCM_CD && (prev.dcd != cur.dcd)) || + (arg & TIOCM_CTS && (prev.cts != cur.cts))) + return 0; + } + return 0; +} + static int ssu100_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; struct ssu100_port_private *priv = usb_get_serial_port_data(port); + void __user *user_arg = (void __user *)arg; dbg("%s cmd 0x%04x", __func__, cmd); @@ -412,28 +431,28 @@ static int ssu100_ioctl(struct tty_struct *tty, struct file *file, (struct serial_struct __user *) arg); case TIOCMIWAIT: - while (priv != NULL) { - u8 prevMSR = priv->shadowMSR & SERIAL_MSR_MASK; - interruptible_sleep_on(&priv->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - else { - u8 diff = (priv->shadowMSR & SERIAL_MSR_MASK) ^ prevMSR; - if (!diff) - return -EIO; /* no change => error */ - - /* Return 0 if caller wanted to know about - these bits */ - - if (((arg & TIOCM_RNG) && (diff & SERIAL_MSR_RI)) || - ((arg & TIOCM_DSR) && (diff & SERIAL_MSR_DSR)) || - ((arg & TIOCM_CD) && (diff & SERIAL_MSR_CD)) || - ((arg & TIOCM_CTS) && (diff & SERIAL_MSR_CTS))) - return 0; - } - } + return wait_modem_info(port, arg); + + case TIOCGICOUNT: + { + struct serial_icounter_struct icount; + struct async_icount cnow = priv->icount; + memset(&icount, 0, sizeof(icount)); + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + if (copy_to_user(user_arg, &icount, sizeof(icount))) + return -EFAULT; return 0; + } default: break; @@ -455,6 +474,7 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port) unsigned num_endpoints; int i; + unsigned long flags; num_endpoints = interface->cur_altsetting->desc.bNumEndpoints; dev_info(&udev->dev, "Number of endpoints %d\n", num_endpoints); @@ -466,7 +486,9 @@ static void ssu100_set_max_packet_size(struct usb_serial_port *port) } /* set max packet size based on descriptor */ + spin_lock_irqsave(&priv->status_lock, flags); priv->max_packet_size = ep_desc->wMaxPacketSize; + spin_unlock_irqrestore(&priv->status_lock, flags); dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); } @@ -485,9 +507,9 @@ static int ssu100_attach(struct usb_serial *serial) return -ENOMEM; } + spin_lock_init(&priv->status_lock); init_waitqueue_head(&priv->delta_msr_wait); usb_set_serial_port_data(port, priv); - ssu100_set_max_packet_size(port); return ssu100_initdevice(serial->dev); @@ -506,20 +528,20 @@ static int ssu100_tiocmget(struct tty_struct *tty, struct file *file) if (!d) return -ENOMEM; - r = ssu100_getregister(dev, 0, MODEM_CTL_REGISTER, d); + r = ssu100_getregister(dev, 0, UART_MCR, d); if (r < 0) goto mget_out; - r = ssu100_getregister(dev, 0, MODEM_STATUS_REGISTER, d+1); + r = ssu100_getregister(dev, 0, UART_MSR, d+1); if (r < 0) goto mget_out; - r = (d[0] & SERIAL_MCR_DTR ? TIOCM_DTR : 0) | - (d[0] & SERIAL_MCR_RTS ? TIOCM_RTS : 0) | - (d[1] & SERIAL_MSR_CTS ? TIOCM_CTS : 0) | - (d[1] & SERIAL_MSR_CD ? TIOCM_CAR : 0) | - (d[1] & SERIAL_MSR_RI ? TIOCM_RI : 0) | - (d[1] & SERIAL_MSR_DSR ? TIOCM_DSR : 0); + r = (d[0] & UART_MCR_DTR ? TIOCM_DTR : 0) | + (d[0] & UART_MCR_RTS ? TIOCM_RTS : 0) | + (d[1] & UART_MSR_CTS ? TIOCM_CTS : 0) | + (d[1] & UART_MSR_DCD ? TIOCM_CAR : 0) | + (d[1] & UART_MSR_RI ? TIOCM_RI : 0) | + (d[1] & UART_MSR_DSR ? TIOCM_DSR : 0); mget_out: kfree(d); @@ -546,7 +568,7 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) if (!port->serial->disconnected) { /* Disable flow control */ if (!on && - ssu100_setregister(dev, 0, 0) < 0) + ssu100_setregister(dev, 0, UART_MCR, 0) < 0) dev_err(&port->dev, "error from flowcontrol urb\n"); /* drop RTS and DTR */ if (on) @@ -557,34 +579,88 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) mutex_unlock(&port->serial->disc_mutex); } +static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) +{ + struct ssu100_port_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->status_lock, flags); + priv->shadowMSR = msr; + spin_unlock_irqrestore(&priv->status_lock, flags); + + if (msr & UART_MSR_ANY_DELTA) { + /* update input line counters */ + if (msr & UART_MSR_DCTS) + priv->icount.cts++; + if (msr & UART_MSR_DDSR) + priv->icount.dsr++; + if (msr & UART_MSR_DDCD) + priv->icount.dcd++; + if (msr & UART_MSR_TERI) + priv->icount.rng++; + wake_up_interruptible(&priv->delta_msr_wait); + } +} + +static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr, + char *tty_flag) +{ + struct ssu100_port_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->status_lock, flags); + priv->shadowLSR = lsr; + spin_unlock_irqrestore(&priv->status_lock, flags); + + *tty_flag = TTY_NORMAL; + if (lsr & UART_LSR_BRK_ERROR_BITS) { + /* we always want to update icount, but we only want to + * update tty_flag for one case */ + if (lsr & UART_LSR_BI) { + priv->icount.brk++; + *tty_flag = TTY_BREAK; + usb_serial_handle_break(port); + } + if (lsr & UART_LSR_PE) { + priv->icount.parity++; + if (*tty_flag == TTY_NORMAL) + *tty_flag = TTY_PARITY; + } + if (lsr & UART_LSR_FE) { + priv->icount.frame++; + if (*tty_flag == TTY_NORMAL) + *tty_flag = TTY_FRAME; + } + if (lsr & UART_LSR_OE){ + priv->icount.overrun++; + if (*tty_flag == TTY_NORMAL) + *tty_flag = TTY_OVERRUN; + } + } + +} + static int ssu100_process_packet(struct tty_struct *tty, struct usb_serial_port *port, struct ssu100_port_private *priv, char *packet, int len) { int i; - char flag; + char flag = TTY_NORMAL; char *ch; dbg("%s - port %d", __func__, port->number); - if (len < 4) { - dbg("%s - malformed packet", __func__); - return 0; - } - - if ((packet[0] == 0x1b) && (packet[1] == 0x1b) && + if ((len >= 4) && + (packet[0] == 0x1b) && (packet[1] == 0x1b) && ((packet[2] == 0x00) || (packet[2] == 0x01))) { - if (packet[2] == 0x00) - priv->shadowLSR = packet[3] & (SERIAL_LSR_OE | - SERIAL_LSR_PE | - SERIAL_LSR_FE | - SERIAL_LSR_BI); - - if (packet[2] == 0x01) { - priv->shadowMSR = packet[3]; - wake_up_interruptible(&priv->delta_msr_wait); + if (packet[2] == 0x00) { + ssu100_update_lsr(port, packet[3], &flag); + if (flag == TTY_OVERRUN) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } + if (packet[2] == 0x01) + ssu100_update_msr(port, packet[3]); len -= 4; ch = packet + 4; @@ -596,7 +672,7 @@ static int ssu100_process_packet(struct tty_struct *tty, if (port->port.console && port->sysrq) { for (i = 0; i < len; i++, ch++) { - if (!usb_serial_handle_sysrq_char(tty, port, *ch)) + if (!usb_serial_handle_sysrq_char(port, *ch)) tty_insert_flip_char(tty, *ch, flag); } } else @@ -631,7 +707,6 @@ static void ssu100_process_read_urb(struct urb *urb) tty_kref_put(tty); } - static struct usb_serial_driver ssu100_device = { .driver = { .owner = THIS_MODULE, @@ -653,6 +728,7 @@ static struct usb_serial_driver ssu100_device = { .tiocmset = ssu100_tiocmset, .ioctl = ssu100_ioctl, .set_termios = ssu100_set_termios, + .disconnect = usb_serial_generic_disconnect, }; static int __init ssu100_init(void) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 2a982e62963b..7a2177c79bde 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -736,6 +736,7 @@ int usb_serial_probe(struct usb_interface *interface, serial = create_serial(dev, interface, type); if (!serial) { + module_put(type->driver.owner); dev_err(&interface->dev, "%s - out of memory\n", __func__); return -ENOMEM; } @@ -746,11 +747,11 @@ int usb_serial_probe(struct usb_interface *interface, id = get_iface_id(type, interface); retval = type->probe(serial, id); - module_put(type->driver.owner); if (retval) { dbg("sub driver rejected device"); kfree(serial); + module_put(type->driver.owner); return retval; } } @@ -822,6 +823,7 @@ int usb_serial_probe(struct usb_interface *interface, if (num_bulk_in == 0 || num_bulk_out == 0) { dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); kfree(serial); + module_put(type->driver.owner); return -ENODEV; } } @@ -835,22 +837,15 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); kfree(serial); + module_put(type->driver.owner); return -EIO; } } #endif if (!num_ports) { /* if this device type has a calc_num_ports function, call it */ - if (type->calc_num_ports) { - if (!try_module_get(type->driver.owner)) { - dev_err(&interface->dev, - "module get failed, exiting\n"); - kfree(serial); - return -EIO; - } + if (type->calc_num_ports) num_ports = type->calc_num_ports(serial); - module_put(type->driver.owner); - } if (!num_ports) num_ports = type->num_ports; } @@ -1039,13 +1034,7 @@ int usb_serial_probe(struct usb_interface *interface, /* if this device type has an attach function, call it */ if (type->attach) { - if (!try_module_get(type->driver.owner)) { - dev_err(&interface->dev, - "module get failed, exiting\n"); - goto probe_error; - } retval = type->attach(serial); - module_put(type->driver.owner); if (retval < 0) goto probe_error; serial->attached = 1; @@ -1088,10 +1077,12 @@ int usb_serial_probe(struct usb_interface *interface, exit: /* success */ usb_set_intfdata(interface, serial); + module_put(type->driver.owner); return 0; probe_error: usb_serial_put(serial); + module_put(type->driver.owner); return -EIO; } EXPORT_SYMBOL_GPL(usb_serial_probe); diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 29e850a7a2f9..7c8008225ee3 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -243,7 +243,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, int r, nlogs = 0; while (datalen > 0) { - if (unlikely(headcount >= VHOST_NET_MAX_SG)) { + if (unlikely(seg >= VHOST_NET_MAX_SG)) { r = -ENOBUFS; goto err; } diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index e05557d52999..dd3d6f7406f8 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -60,22 +60,25 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync, return 0; } +static void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn) +{ + INIT_LIST_HEAD(&work->node); + work->fn = fn; + init_waitqueue_head(&work->done); + work->flushing = 0; + work->queue_seq = work->done_seq = 0; +} + /* Init poll structure */ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, unsigned long mask, struct vhost_dev *dev) { - struct vhost_work *work = &poll->work; - init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup); init_poll_funcptr(&poll->table, vhost_poll_func); poll->mask = mask; poll->dev = dev; - INIT_LIST_HEAD(&work->node); - work->fn = fn; - init_waitqueue_head(&work->done); - work->flushing = 0; - work->queue_seq = work->done_seq = 0; + vhost_work_init(&poll->work, fn); } /* Start polling a file. We add ourselves to file's wait queue. The caller must @@ -95,35 +98,38 @@ void vhost_poll_stop(struct vhost_poll *poll) remove_wait_queue(poll->wqh, &poll->wait); } -/* Flush any work that has been scheduled. When calling this, don't hold any - * locks that are also used by the callback. */ -void vhost_poll_flush(struct vhost_poll *poll) +static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work) { - struct vhost_work *work = &poll->work; unsigned seq; int left; int flushing; - spin_lock_irq(&poll->dev->work_lock); + spin_lock_irq(&dev->work_lock); seq = work->queue_seq; work->flushing++; - spin_unlock_irq(&poll->dev->work_lock); + spin_unlock_irq(&dev->work_lock); wait_event(work->done, ({ - spin_lock_irq(&poll->dev->work_lock); + spin_lock_irq(&dev->work_lock); left = seq - work->done_seq <= 0; - spin_unlock_irq(&poll->dev->work_lock); + spin_unlock_irq(&dev->work_lock); left; })); - spin_lock_irq(&poll->dev->work_lock); + spin_lock_irq(&dev->work_lock); flushing = --work->flushing; - spin_unlock_irq(&poll->dev->work_lock); + spin_unlock_irq(&dev->work_lock); BUG_ON(flushing < 0); } -void vhost_poll_queue(struct vhost_poll *poll) +/* Flush any work that has been scheduled. When calling this, don't hold any + * locks that are also used by the callback. */ +void vhost_poll_flush(struct vhost_poll *poll) +{ + vhost_work_flush(poll->dev, &poll->work); +} + +static inline void vhost_work_queue(struct vhost_dev *dev, + struct vhost_work *work) { - struct vhost_dev *dev = poll->dev; - struct vhost_work *work = &poll->work; unsigned long flags; spin_lock_irqsave(&dev->work_lock, flags); @@ -135,6 +141,11 @@ void vhost_poll_queue(struct vhost_poll *poll) spin_unlock_irqrestore(&dev->work_lock, flags); } +void vhost_poll_queue(struct vhost_poll *poll) +{ + vhost_work_queue(poll->dev, &poll->work); +} + static void vhost_vq_reset(struct vhost_dev *dev, struct vhost_virtqueue *vq) { @@ -236,6 +247,29 @@ long vhost_dev_check_owner(struct vhost_dev *dev) return dev->mm == current->mm ? 0 : -EPERM; } +struct vhost_attach_cgroups_struct { + struct vhost_work work; + struct task_struct *owner; + int ret; +}; + +static void vhost_attach_cgroups_work(struct vhost_work *work) +{ + struct vhost_attach_cgroups_struct *s; + s = container_of(work, struct vhost_attach_cgroups_struct, work); + s->ret = cgroup_attach_task_all(s->owner, current); +} + +static int vhost_attach_cgroups(struct vhost_dev *dev) +{ + struct vhost_attach_cgroups_struct attach; + attach.owner = current; + vhost_work_init(&attach.work, vhost_attach_cgroups_work); + vhost_work_queue(dev, &attach.work); + vhost_work_flush(dev, &attach.work); + return attach.ret; +} + /* Caller should have device mutex */ static long vhost_dev_set_owner(struct vhost_dev *dev) { @@ -255,14 +289,16 @@ static long vhost_dev_set_owner(struct vhost_dev *dev) } dev->worker = worker; - err = cgroup_attach_task_current_cg(worker); + wake_up_process(worker); /* avoid contributing to loadavg */ + + err = vhost_attach_cgroups(dev); if (err) goto err_cgroup; - wake_up_process(worker); /* avoid contributing to loadavg */ return 0; err_cgroup: kthread_stop(worker); + dev->worker = NULL; err_worker: if (dev->mm) mmput(dev->mm); @@ -323,7 +359,10 @@ void vhost_dev_cleanup(struct vhost_dev *dev) dev->mm = NULL; WARN_ON(!list_empty(&dev->work_list)); - kthread_stop(dev->worker); + if (dev->worker) { + kthread_stop(dev->worker); + dev->worker = NULL; + } } static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz) @@ -819,11 +858,12 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, if (r < 0) return r; len -= l; - if (!len) + if (!len) { + if (vq->log_ctx) + eventfd_signal(vq->log_ctx, 1); return 0; + } } - if (vq->log_ctx) - eventfd_signal(vq->log_ctx, 1); /* Length written exceeds what we have stored. This is a bug. */ BUG(); return 0; diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 84f842331dfa..7ccc967831f0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3508,7 +3508,7 @@ static void fbcon_exit(void) softback_buf = 0UL; for (i = 0; i < FB_MAX; i++) { - int pending; + int pending = 0; mapped = 0; info = registered_fb[i]; @@ -3516,7 +3516,8 @@ static void fbcon_exit(void) if (info == NULL) continue; - pending = cancel_work_sync(&info->queue); + if (info->queue.func) + pending = cancel_work_sync(&info->queue); DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" : "no")); diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 815f84b07933..70477c2e4b61 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -13,7 +13,7 @@ #include <linux/platform_device.h> #include <linux/screen_info.h> #include <linux/dmi.h> - +#include <linux/pci.h> #include <video/vga.h> static struct fb_var_screeninfo efifb_defined __devinitdata = { @@ -39,17 +39,31 @@ enum { M_I20, /* 20-Inch iMac */ M_I20_SR, /* 20-Inch iMac (Santa Rosa) */ M_I24, /* 24-Inch iMac */ + M_I24_8_1, /* 24-Inch iMac, 8,1th gen */ + M_I24_10_1, /* 24-Inch iMac, 10,1th gen */ + M_I27_11_1, /* 27-Inch iMac, 11,1th gen */ M_MINI, /* Mac Mini */ + M_MINI_3_1, /* Mac Mini, 3,1th gen */ + M_MINI_4_1, /* Mac Mini, 4,1th gen */ M_MB, /* MacBook */ M_MB_2, /* MacBook, 2nd rev. */ M_MB_3, /* MacBook, 3rd rev. */ + M_MB_5_1, /* MacBook, 5th rev. */ + M_MB_6_1, /* MacBook, 6th rev. */ + M_MB_7_1, /* MacBook, 7th rev. */ M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ M_MBA, /* MacBook Air */ M_MBP, /* MacBook Pro */ M_MBP_2, /* MacBook Pro 2nd gen */ + M_MBP_2_2, /* MacBook Pro 2,2nd gen */ M_MBP_SR, /* MacBook Pro (Santa Rosa) */ M_MBP_4, /* MacBook Pro, 4th gen */ M_MBP_5_1, /* MacBook Pro, 5,1th gen */ + M_MBP_5_2, /* MacBook Pro, 5,2th gen */ + M_MBP_5_3, /* MacBook Pro, 5,3rd gen */ + M_MBP_6_1, /* MacBook Pro, 6,1th gen */ + M_MBP_6_2, /* MacBook Pro, 6,2th gen */ + M_MBP_7_1, /* MacBook Pro, 7,1th gen */ M_UNKNOWN /* placeholder */ }; @@ -64,14 +78,28 @@ static struct efifb_dmi_info { [M_I20] = { "i20", 0x80010000, 1728 * 4, 1680, 1050 }, /* guess */ [M_I20_SR] = { "imac7", 0x40010000, 1728 * 4, 1680, 1050 }, [M_I24] = { "i24", 0x80010000, 2048 * 4, 1920, 1200 }, /* guess */ + [M_I24_8_1] = { "imac8", 0xc0060000, 2048 * 4, 1920, 1200 }, + [M_I24_10_1] = { "imac10", 0xc0010000, 2048 * 4, 1920, 1080 }, + [M_I27_11_1] = { "imac11", 0xc0010000, 2560 * 4, 2560, 1440 }, [M_MINI]= { "mini", 0x80000000, 2048 * 4, 1024, 768 }, + [M_MINI_3_1] = { "mini31", 0x40010000, 1024 * 4, 1024, 768 }, + [M_MINI_4_1] = { "mini41", 0xc0010000, 2048 * 4, 1920, 1200 }, [M_MB] = { "macbook", 0x80000000, 2048 * 4, 1280, 800 }, + [M_MB_5_1] = { "macbook51", 0x80010000, 2048 * 4, 1280, 800 }, + [M_MB_6_1] = { "macbook61", 0x80010000, 2048 * 4, 1280, 800 }, + [M_MB_7_1] = { "macbook71", 0x80010000, 2048 * 4, 1280, 800 }, [M_MBA] = { "mba", 0x80000000, 2048 * 4, 1280, 800 }, [M_MBP] = { "mbp", 0x80010000, 1472 * 4, 1440, 900 }, [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ + [M_MBP_2_2] = { "mbp22", 0x80010000, 1472 * 4, 1440, 900 }, [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, + [M_MBP_5_2] = { "mbp52", 0xc0010000, 2048 * 4, 1920, 1200 }, + [M_MBP_5_3] = { "mbp53", 0xd0010000, 2048 * 4, 1440, 900 }, + [M_MBP_6_1] = { "mbp61", 0x90030000, 2048 * 4, 1920, 1200 }, + [M_MBP_6_2] = { "mbp62", 0x90030000, 2048 * 4, 1680, 1050 }, + [M_MBP_7_1] = { "mbp71", 0xc0010000, 2048 * 4, 1280, 800 }, [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } }; @@ -92,7 +120,12 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "iMac6,1", M_I24), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac6,1", M_I24), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac7,1", M_I20_SR), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac8,1", M_I24_8_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac10,1", M_I24_10_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "iMac11,1", M_I27_11_1), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "Macmini1,1", M_MINI), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini3,1", M_MINI_3_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "Macmini4,1", M_MINI_4_1), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook1,1", M_MB), /* At least one of these two will be right; maybe both? */ EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook2,1", M_MB), @@ -101,14 +134,23 @@ static const struct dmi_system_id dmi_system_table[] __initconst = { EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBook3,1", M_MB), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook3,1", M_MB), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook4,1", M_MB), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook5,1", M_MB_5_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook6,1", M_MB_6_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBook7,1", M_MB_7_1), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookAir1,1", M_MBA), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro1,1", M_MBP), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,1", M_MBP_2), + EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro2,2", M_MBP_2_2), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro2,1", M_MBP_2), EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,2", M_MBP_5_2), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,3", M_MBP_5_3), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,1", M_MBP_6_1), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro6,2", M_MBP_6_2), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro7,1", M_MBP_7_1), {}, }; @@ -116,7 +158,7 @@ static int set_system(const struct dmi_system_id *id) { struct efifb_dmi_info *info = id->driver_data; if (info->base == 0) - return -ENODEV; + return 0; printk(KERN_INFO "efifb: dmi detected %s - framebuffer at %p " "(%dx%d, stride %d)\n", id->ident, @@ -124,18 +166,55 @@ static int set_system(const struct dmi_system_id *id) info->stride); /* Trust the bootloader over the DMI tables */ - if (screen_info.lfb_base == 0) + if (screen_info.lfb_base == 0) { +#if defined(CONFIG_PCI) + struct pci_dev *dev = NULL; + int found_bar = 0; +#endif screen_info.lfb_base = info->base; - if (screen_info.lfb_linelength == 0) - screen_info.lfb_linelength = info->stride; - if (screen_info.lfb_width == 0) - screen_info.lfb_width = info->width; - if (screen_info.lfb_height == 0) - screen_info.lfb_height = info->height; - if (screen_info.orig_video_isVGA == 0) - screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; - return 0; +#if defined(CONFIG_PCI) + /* make sure that the address in the table is actually on a + * VGA device's PCI BAR */ + + for_each_pci_dev(dev) { + int i; + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + continue; + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + resource_size_t start, end; + + start = pci_resource_start(dev, i); + if (start == 0) + break; + end = pci_resource_end(dev, i); + if (screen_info.lfb_base >= start && + screen_info.lfb_base < end) { + found_bar = 1; + } + } + } + if (!found_bar) + screen_info.lfb_base = 0; +#endif + } + if (screen_info.lfb_base) { + if (screen_info.lfb_linelength == 0) + screen_info.lfb_linelength = info->stride; + if (screen_info.lfb_width == 0) + screen_info.lfb_width = info->width; + if (screen_info.lfb_height == 0) + screen_info.lfb_height = info->height; + if (screen_info.orig_video_isVGA == 0) + screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; + } else { + screen_info.lfb_linelength = 0; + screen_info.lfb_width = 0; + screen_info.lfb_height = 0; + screen_info.orig_video_isVGA = 0; + return 0; + } + return 1; } static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c index c91a7f70f7b0..a31a77ff6f3d 100644 --- a/drivers/video/pxa168fb.c +++ b/drivers/video/pxa168fb.c @@ -298,8 +298,8 @@ static void set_dma_control0(struct pxa168fb_info *fbi) * Set bit to enable graphics DMA. */ x = readl(fbi->reg_base + LCD_SPU_DMA_CTRL0); - x |= fbi->active ? 0x00000100 : 0; - fbi->active = 0; + x &= ~CFG_GRA_ENA_MASK; + x |= fbi->active ? CFG_GRA_ENA(1) : CFG_GRA_ENA(0); /* * If we are in a pseudo-color mode, we need to enable @@ -559,7 +559,7 @@ static struct fb_ops pxa168fb_ops = { .fb_imageblit = cfb_imageblit, }; -static int __init pxa168fb_init_mode(struct fb_info *info, +static int __devinit pxa168fb_init_mode(struct fb_info *info, struct pxa168fb_mach_info *mi) { struct pxa168fb_info *fbi = info->par; @@ -599,7 +599,7 @@ static int __init pxa168fb_init_mode(struct fb_info *info, return ret; } -static int __init pxa168fb_probe(struct platform_device *pdev) +static int __devinit pxa168fb_probe(struct platform_device *pdev) { struct pxa168fb_mach_info *mi; struct fb_info *info = 0; @@ -792,7 +792,7 @@ static struct platform_driver pxa168fb_driver = { .probe = pxa168fb_probe, }; -static int __devinit pxa168fb_init(void) +static int __init pxa168fb_init(void) { return platform_driver_register(&pxa168fb_driver); } diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 559bf1727a2b..b52f8e4ef1fd 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1701,6 +1701,9 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, break; case FBIOGET_VBLANK: + + memset(&sisvbblank, 0, sizeof(struct fb_vblank)); + sisvbblank.count = 0; sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount); diff --git a/drivers/video/via/ioctl.c b/drivers/video/via/ioctl.c index da03c074e32a..4d553d0b8d7a 100644 --- a/drivers/video/via/ioctl.c +++ b/drivers/video/via/ioctl.c @@ -25,6 +25,8 @@ int viafb_ioctl_get_viafb_info(u_long arg) { struct viafb_ioctl_info viainfo; + memset(&viainfo, 0, sizeof(struct viafb_ioctl_info)); + viainfo.viafb_id = VIAID; viainfo.vendor_id = PCI_VIA_VENDOR_ID; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b036677df8c4..24efd8ea41bb 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -213,11 +213,11 @@ config OMAP_WATCHDOG here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. config PNX4008_WATCHDOG - tristate "PNX4008 Watchdog" - depends on ARCH_PNX4008 + tristate "PNX4008 and LPC32XX Watchdog" + depends on ARCH_PNX4008 || ARCH_LPC32XX help Say Y here if to include support for the watchdog timer - in the PNX4008 processor. + in the PNX4008 or LPC32XX processor. This driver can be built as a module by choosing M. The module will be called pnx4008_wdt. diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 88c83aa57303..f31493e65b38 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -305,7 +305,7 @@ static int __init sbwdog_init(void) if (ret) { printk(KERN_ERR "%s: failed to request irq 1 - %d\n", ident.identity, ret); - return ret; + goto out; } ret = misc_register(&sbwdog_miscdev); @@ -313,14 +313,20 @@ static int __init sbwdog_init(void) printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", ident.identity, timeout / 1000000, (timeout / 100000) % 10); - } else - free_irq(1, (void *)user_dog); + return 0; + } + free_irq(1, (void *)user_dog); +out: + unregister_reboot_notifier(&sbwdog_notifier); + return ret; } static void __exit sbwdog_exit(void) { misc_deregister(&sbwdog_miscdev); + free_irq(1, (void *)user_dog); + unregister_reboot_notifier(&sbwdog_notifier); } module_init(sbwdog_init); diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 458c499c1223..18cdeb4c4258 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -449,6 +449,9 @@ static __devinit int ts72xx_wdt_probe(struct platform_device *pdev) wdt->pdev = pdev; mutex_init(&wdt->lock); + /* make sure that the watchdog is disabled */ + ts72xx_wdt_stop(wdt); + error = misc_register(&ts72xx_wdt_miscdev); if (error) { dev_err(&pdev->dev, "failed to register miscdev\n"); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 72f91bff29c7..13365ba35218 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -112,6 +112,7 @@ static inline unsigned long *cpu_evtchn_mask(int cpu) #define VALID_EVTCHN(chn) ((chn) != 0) static struct irq_chip xen_dynamic_chip; +static struct irq_chip xen_percpu_chip; /* Constructor for packed IRQ information. */ static struct irq_info mk_unbound_info(void) @@ -377,7 +378,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) irq = find_unbound_irq(); set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_level_irq, "event"); + handle_edge_irq, "event"); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_evtchn_info(evtchn); @@ -403,8 +404,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) if (irq < 0) goto out; - set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_level_irq, "ipi"); + set_irq_chip_and_handler_name(irq, &xen_percpu_chip, + handle_percpu_irq, "ipi"); bind_ipi.vcpu = cpu; if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, @@ -444,8 +445,8 @@ static int bind_virq_to_irq(unsigned int virq, unsigned int cpu) irq = find_unbound_irq(); - set_irq_chip_and_handler_name(irq, &xen_dynamic_chip, - handle_level_irq, "virq"); + set_irq_chip_and_handler_name(irq, &xen_percpu_chip, + handle_percpu_irq, "virq"); evtchn_to_irq[evtchn] = irq; irq_info[irq] = mk_virq_info(evtchn, virq); @@ -964,6 +965,16 @@ static struct irq_chip xen_dynamic_chip __read_mostly = { .retrigger = retrigger_dynirq, }; +static struct irq_chip xen_percpu_chip __read_mostly = { + .name = "xen-percpu", + + .disable = disable_dynirq, + .mask = disable_dynirq, + .unmask = enable_dynirq, + + .ack = ack_dynirq, +}; + int xen_set_callback_via(uint64_t via) { struct xen_hvm_param a; diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 1799bd890315..ef9c7db52077 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -237,7 +237,7 @@ static void sysrq_handler(struct xenbus_watch *watch, const char **vec, goto again; if (sysrq_key != '\0') - handle_sysrq(sysrq_key, NULL); + handle_sysrq(sysrq_key); } static struct xenbus_watch sysrq_watch = { diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 29bac5118877..d409495876f1 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -755,7 +755,10 @@ int register_xenstore_notifier(struct notifier_block *nb) { int ret = 0; - blocking_notifier_chain_register(&xenstore_chain, nb); + if (xenstored_ready > 0) + ret = nb->notifier_call(nb, 0, NULL); + else + blocking_notifier_chain_register(&xenstore_chain, nb); return ret; } @@ -769,7 +772,7 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_notifier); void xenbus_probe(struct work_struct *unused) { - BUG_ON((xenstored_ready <= 0)); + xenstored_ready = 1; /* Enumerate devices in xenstore and watch for changes. */ xenbus_probe_devices(&xenbus_frontend); @@ -835,8 +838,8 @@ static int __init xenbus_init(void) xen_store_evtchn = xen_start_info->store_evtchn; xen_store_mfn = xen_start_info->store_mfn; xen_store_interface = mfn_to_virt(xen_store_mfn); + xenstored_ready = 1; } - xenstored_ready = 1; } /* Initialize the interface to xenstore. */ |