From 70c66567d1e41d8b2186a2d198997a1c8d79c0c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Wed, 9 Dec 2009 22:09:53 +0100 Subject: HID: blacklist ET&T TC5UH touchscreen controller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds ET&T TC5UH touchscreen controller to HID blacklist, because this device is handled by input/usbtouchscreen driver. Signed-off-by: Petr Štetiar Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 80792d38d25..389cd5f0a68 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1553,6 +1553,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 3839340e293..b9de32b6b10 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -166,6 +166,9 @@ #define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 +#define USB_VENDOR_ID_ETT 0x0664 +#define USB_DEVICE_ID_TC5UH 0x0309 + #define USB_VENDOR_ID_EZKEY 0x0518 #define USB_DEVICE_ID_BTC_8193 0x0002 -- cgit v1.2.3 From 3975bc56305256af7689bcce62284fc62e09fc8f Mon Sep 17 00:00:00 2001 From: Robert Schedel Date: Fri, 11 Dec 2009 00:37:11 +0100 Subject: HID: Support 171 byte variant of Samsung USB IR receiver Extends the existing Samsung USB IrDA (0419:0001) quirk with newly reported 171 byte variant. It needs the same quirk as the other devices already supported by hid-samsung (wrong logical range) Refactors duplicate trace call into local helper function. The original bug report for the new variant is available at the second half of this ticket page: https://bugs.launchpad.net/bugs/326986 Signed-off-by: Robert Schedel Signed-off-by: Jiri Kosina --- drivers/hid/hid-samsung.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index 5b222eed069..510dd134059 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c @@ -39,7 +39,17 @@ * * 3. 135 byte report descriptor * Report #4 has an array field with logical range 0..17 instead of 1..14. + * + * 4. 171 byte report descriptor + * Report #3 has an array field with logical range 0..1 instead of 1..3. */ +static inline void samsung_dev_trace(struct hid_device *hdev, + unsigned int rsize) +{ + dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " + "descriptor\n", rsize); +} + static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int rsize) { @@ -47,8 +57,7 @@ static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[177] == 0x75 && rdesc[178] == 0x30 && rdesc[179] == 0x95 && rdesc[180] == 0x01 && rdesc[182] == 0x40) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", 184); + samsung_dev_trace(hdev, 184); rdesc[176] = 0xff; rdesc[178] = 0x08; rdesc[180] = 0x06; @@ -56,17 +65,21 @@ static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, } else if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && rdesc[194] == 0x25 && rdesc[195] == 0x12) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", 203); + samsung_dev_trace(hdev, 203); rdesc[193] = 0x1; rdesc[195] = 0xf; } else if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && rdesc[126] == 0x25 && rdesc[127] == 0x11) { - dev_info(&hdev->dev, "fixing up Samsung IrDA %d byte report " - "descriptor\n", 135); + samsung_dev_trace(hdev, 135); rdesc[125] = 0x1; rdesc[127] = 0xe; + } else + if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && + rdesc[162] == 0x25 && rdesc[163] == 0x01) { + samsung_dev_trace(hdev, 171); + rdesc[161] = 0x1; + rdesc[163] = 0x3; } } -- cgit v1.2.3 From 656cb79322319a7bbafec7912d262142e9a38bc0 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 14 Dec 2009 13:12:45 -0800 Subject: drm/i915: In the debugfs interface, unmap our address instead of the page's. Fixes a BUG_ON in kmap_atomic for the following atomic mapping with USER0 type. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 18476bf0b58..463e8d0155c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -272,7 +272,7 @@ static void i915_dump_pages(struct seq_file *m, struct page **pages, int page_co mem = kmap_atomic(pages[page], KM_USER0); for (i = 0; i < PAGE_SIZE; i += 4) seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); - kunmap_atomic(pages[page], KM_USER0); + kunmap_atomic(mem, KM_USER0); } } -- cgit v1.2.3 From 96b47b65594fe2365f73aede060cb5203561fed3 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Dec 2009 17:50:00 +0100 Subject: drm/i915: fix order of fence release wrt flushing i915_gem_object_unbind had the ordering wrong. The other user, i915_gem_object_put_fence_reg already has the correct ordering. Results was usually corrupted pixmaps, especially garbled font glyphs after a suspend/resume (because this evicts everything). I'm still waiting for the feedback from the bug-reporters, but because this obviously fixes a bug (at least for me) I'm already submitting it. Bugzilla: http://bugs.freedesktop.org/show_bug.cgi?id=25406 Signed-off-by: Daniel Vetter Signed-off-by: Eric Anholt CC: stable@kernel.org --- drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8c463cf2050..9e81a0ddafa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2021,9 +2021,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj) /* blow away mappings if mapped through GTT */ i915_gem_release_mmap(obj); - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - i915_gem_clear_fence_reg(obj); - /* Move the object to the CPU domain to ensure that * any possible CPU writes while it's not in the GTT * are flushed when we go to remap it. This will @@ -2039,6 +2036,10 @@ i915_gem_object_unbind(struct drm_gem_object *obj) BUG_ON(obj_priv->active); + /* release the fence reg _after_ flushing */ + if (obj_priv->fence_reg != I915_FENCE_REG_NONE) + i915_gem_clear_fence_reg(obj); + if (obj_priv->agp_mem != NULL) { drm_unbind_agp(obj_priv->agp_mem); drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); -- cgit v1.2.3 From 11ba159288f1bfc1a475c994e598f5fe423fde9d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 15 Dec 2009 13:55:24 -0500 Subject: drm/i915: Don't check for lid presence when detecting LVDS Checking for the presence of a lid in order to validate whether or not an LVDS display exists fails on some development platforms that implement a lid device but allow the LVDS to be disabled. The VBT is correctly updated, but Linux assumes that an LVDS is still present and lies to userspace. Remove the lid check and trust the VBT. Signed-off-by: Matthew Garrett Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 67 ++------------------------------------- 1 file changed, 2 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 3118ce274e6..539d97ee79e 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -854,65 +854,6 @@ static const struct dmi_system_id intel_no_lvds[] = { { } /* terminating entry */ }; -#ifdef CONFIG_ACPI -/* - * check_lid_device -- check whether @handle is an ACPI LID device. - * @handle: ACPI device handle - * @level : depth in the ACPI namespace tree - * @context: the number of LID device when we find the device - * @rv: a return value to fill if desired (Not use) - */ -static acpi_status -check_lid_device(acpi_handle handle, u32 level, void *context, - void **return_value) -{ - struct acpi_device *acpi_dev; - int *lid_present = context; - - acpi_dev = NULL; - /* Get the acpi device for device handle */ - if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) { - /* If there is no ACPI device for handle, return */ - return AE_OK; - } - - if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7)) - *lid_present = 1; - - return AE_OK; -} - -/** - * check whether there exists the ACPI LID device by enumerating the ACPI - * device tree. - */ -static int intel_lid_present(void) -{ - int lid_present = 0; - - if (acpi_disabled) { - /* If ACPI is disabled, there is no ACPI device tree to - * check, so assume the LID device would have been present. - */ - return 1; - } - - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - check_lid_device, NULL, &lid_present, NULL); - - return lid_present; -} -#else -static int intel_lid_present(void) -{ - /* In the absence of ACPI built in, assume that the LID device would - * have been present. - */ - return 1; -} -#endif - /** * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID * @dev: drm device @@ -1031,12 +972,8 @@ void intel_lvds_init(struct drm_device *dev) if (dmi_check_system(intel_no_lvds)) return; - /* - * Assume LVDS is present if there's an ACPI lid device or if the - * device is present in the VBT. - */ - if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) { - DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n"); + if (!lvds_is_present_in_vbt(dev)) { + DRM_DEBUG_KMS("LVDS is not present in VBT\n"); return; } -- cgit v1.2.3 From cbda12d77ea590082edb6d30bd342a67ebc459e0 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 16 Dec 2009 13:36:10 +0800 Subject: drm/i915: implement new pm ops for i915 One problem in i915 hibernate with current legacy pci pm ops is that after we do freeze, we'll be forced to do resume once again, which re-init some resources and do modesetting again, that is unnecessary for hibernate. This patch trys to bypass that. We can't resolve this within legacy pm framework, but can do it easily with new pm ops. Suspend (S3) process has also been kept without change. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 53 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2fa21786205..6978a22f70e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -284,6 +284,52 @@ i915_pci_resume(struct pci_dev *pdev) return i915_resume(dev); } +static int +i915_pm_suspend(struct device *dev) +{ + return i915_pci_suspend(to_pci_dev(dev), PMSG_SUSPEND); +} + +static int +i915_pm_resume(struct device *dev) +{ + return i915_pci_resume(to_pci_dev(dev)); +} + +static int +i915_pm_freeze(struct device *dev) +{ + return i915_pci_suspend(to_pci_dev(dev), PMSG_FREEZE); +} + +static int +i915_pm_thaw(struct device *dev) +{ + /* thaw during hibernate, do nothing! */ + return 0; +} + +static int +i915_pm_poweroff(struct device *dev) +{ + return i915_pci_suspend(to_pci_dev(dev), PMSG_HIBERNATE); +} + +static int +i915_pm_restore(struct device *dev) +{ + return i915_pci_resume(to_pci_dev(dev)); +} + +const struct dev_pm_ops i915_pm_ops = { + .suspend = i915_pm_suspend, + .resume = i915_pm_resume, + .freeze = i915_pm_freeze, + .thaw = i915_pm_thaw, + .poweroff = i915_pm_poweroff, + .restore = i915_pm_restore, +}; + static struct vm_operations_struct i915_gem_vm_ops = { .fault = i915_gem_fault, .open = drm_gem_vm_open, @@ -303,8 +349,6 @@ static struct drm_driver driver = { .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .postclose = i915_driver_postclose, - .suspend = i915_suspend, - .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, @@ -344,10 +388,7 @@ static struct drm_driver driver = { .id_table = pciidlist, .probe = i915_pci_probe, .remove = i915_pci_remove, -#ifdef CONFIG_PM - .resume = i915_pci_resume, - .suspend = i915_pci_suspend, -#endif + .driver.pm = &i915_pm_ops, }, .name = DRIVER_NAME, -- cgit v1.2.3 From 0ad3dc3af8ba028368263b190a7a270f8d5cf5ae Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 00:36:09 -0800 Subject: tc1100-wmi - switch to using attribute group Sysfs attribute group takes care of proper creation of a set of attributes and implements proper error unwinding so the driver does not have to do it. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index 44166003d4e..0d53d516657 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -183,30 +183,15 @@ static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ show_set_bool(wireless, TC1100_INSTANCE_WIRELESS); show_set_bool(jogdial, TC1100_INSTANCE_JOGDIAL); -static void remove_fs(void) -{ - device_remove_file(&tc1100_device->dev, &dev_attr_wireless); - device_remove_file(&tc1100_device->dev, &dev_attr_jogdial); -} - -static int add_fs(void) -{ - int ret; - - ret = device_create_file(&tc1100_device->dev, &dev_attr_wireless); - if (ret) - goto add_sysfs_error; - - ret = device_create_file(&tc1100_device->dev, &dev_attr_jogdial); - if (ret) - goto add_sysfs_error; - - return ret; +static struct attribute *tc1100_attributes[] = { + &dev_attr_wireless.attr, + &dev_attr_jogdial.attr, + NULL +}; -add_sysfs_error: - remove_fs(); - return ret; -} +static struct attribute_group tc1100_attribute_group = { + .attrs = tc1100_attributes, +}; /* -------------------------------------------------------------------------- Driver Model @@ -214,16 +199,14 @@ add_sysfs_error: static int tc1100_probe(struct platform_device *device) { - int result = 0; - - result = add_fs(); - return result; + return sysfs_create_group(&device->dev.kobj, &tc1100_attribute_group); } static int tc1100_remove(struct platform_device *device) { - remove_fs(); + sysfs_remove_group(&device->dev.kobj, &tc1100_attribute_group); + return 0; } -- cgit v1.2.3 From 9634a627b330fcc7cdca25df4d7853ca9c7745de Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 00:36:15 -0800 Subject: tc1100-wmi - add error handling for device registration Any of the platform API functions can fail; driver should be prepared to handle such failures. Also: - changed to platform_driver_probe() since the device is created right there with the driver; - added __devexit annotation to remove method; - fixed memory leak on module unload - named platform_device_del() is not enough to free platform device, need platform_device_unregister(). Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 58 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index 0d53d516657..fa2995bfa1d 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -47,22 +47,6 @@ MODULE_DESCRIPTION("HP Compaq TC1100 Tablet WMI Extras"); MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:C364AC71-36DB-495A-8494-B439D472A505"); -static int tc1100_probe(struct platform_device *device); -static int tc1100_remove(struct platform_device *device); -static int tc1100_suspend(struct platform_device *device, pm_message_t state); -static int tc1100_resume(struct platform_device *device); - -static struct platform_driver tc1100_driver = { - .driver = { - .name = "tc1100-wmi", - .owner = THIS_MODULE, - }, - .probe = tc1100_probe, - .remove = tc1100_remove, - .suspend = tc1100_suspend, - .resume = tc1100_resume, -}; - static struct platform_device *tc1100_device; struct tc1100_data { @@ -197,13 +181,13 @@ static struct attribute_group tc1100_attribute_group = { Driver Model -------------------------------------------------------------------------- */ -static int tc1100_probe(struct platform_device *device) +static int __init tc1100_probe(struct platform_device *device) { return sysfs_create_group(&device->dev.kobj, &tc1100_attribute_group); } -static int tc1100_remove(struct platform_device *device) +static int __devexit tc1100_remove(struct platform_device *device) { sysfs_remove_group(&device->dev.kobj, &tc1100_attribute_group); @@ -240,31 +224,49 @@ static int tc1100_resume(struct platform_device *dev) return ret; } +static struct platform_driver tc1100_driver = { + .driver = { + .name = "tc1100-wmi", + .owner = THIS_MODULE, + }, + .remove = __devexit_p(tc1100_remove), + .suspend = tc1100_suspend, + .resume = tc1100_resume, +}; + static int __init tc1100_init(void) { - int result = 0; + int error; if (!wmi_has_guid(GUID)) return -ENODEV; - result = platform_driver_register(&tc1100_driver); - if (result) - return result; - tc1100_device = platform_device_alloc("tc1100-wmi", -1); - platform_device_add(tc1100_device); + if (!tc1100_device) + return -ENOMEM; + + error = platform_device_add(tc1100_device); + if (error) + goto err_device_put; + + error = platform_driver_probe(&tc1100_driver, tc1100_probe); + if (error) + goto err_device_del; printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras loaded\n"); + return 0; - return result; + err_device_del: + platform_device_del(tc1100_device); + err_device_put: + platform_device_put(tc1100_device); + return error; } static void __exit tc1100_exit(void) { - platform_device_del(tc1100_device); + platform_device_unregister(tc1100_device); platform_driver_unregister(&tc1100_driver); - - printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras unloaded\n"); } module_init(tc1100_init); -- cgit v1.2.3 From 8e698a3c47887fe5aa5e2252c27bb6ff416a07e4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 00:36:20 -0800 Subject: tc1100-wmi - switch to using dev_pm_ops Also guard PM operations with CONFIG_PM. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index fa2995bfa1d..dd33b51c348 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -194,7 +194,8 @@ static int __devexit tc1100_remove(struct platform_device *device) return 0; } -static int tc1100_suspend(struct platform_device *dev, pm_message_t state) +#ifdef CONFIG_PM +static int tc1100_suspend(struct device *dev) { int ret; @@ -206,10 +207,10 @@ static int tc1100_suspend(struct platform_device *dev, pm_message_t state) if (ret) return ret; - return ret; + return 0; } -static int tc1100_resume(struct platform_device *dev) +static int tc1100_resume(struct device *dev) { int ret; @@ -221,17 +222,26 @@ static int tc1100_resume(struct platform_device *dev) if (ret) return ret; - return ret; + return 0; } +static const struct dev_pm_ops tc1100_pm_ops = { + .suspend = tc1100_suspend, + .resume = tc1100_resume, + .freeze = tc1100_suspend, + .restore = tc1100_resume, +}; +#endif + static struct platform_driver tc1100_driver = { .driver = { .name = "tc1100-wmi", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &tc1100_pm_ops, +#endif }, .remove = __devexit_p(tc1100_remove), - .suspend = tc1100_suspend, - .resume = tc1100_resume, }; static int __init tc1100_init(void) -- cgit v1.2.3 From 4297a462f455e38f08976df7b16c849614a287da Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 16 Dec 2009 16:28:03 +0100 Subject: dma: at_hdmac: correct incompatible type for argument 1 of 'spin_lock_bh' Correct a typo error in locking calls. Cc: Signed-off-by: Nicolas Ferre Signed-off-by: Dan Williams --- drivers/dma/at_hdmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7585c4164bd..c558fa13b4b 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -815,7 +815,7 @@ atc_is_tx_complete(struct dma_chan *chan, dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n", cookie, done ? *done : 0, used ? *used : 0); - spin_lock_bh(atchan->lock); + spin_lock_bh(&atchan->lock); last_complete = atchan->completed_cookie; last_used = chan->cookie; @@ -830,7 +830,7 @@ atc_is_tx_complete(struct dma_chan *chan, ret = dma_async_is_complete(cookie, last_complete, last_used); } - spin_unlock_bh(atchan->lock); + spin_unlock_bh(&atchan->lock); if (done) *done = last_complete; -- cgit v1.2.3 From a3cb5195f6db58dbebd8a31b877ddce082c9b63d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 09:26:10 +0800 Subject: drm/i915: Add MALATA PC-81005 to ACPI LID quirk list The MALATA PC-81005 laptop always reports that the LID status is closed and we can't use it reliabily for LVDS detection. So add this box into the quirk list. https://bugs.freedesktop.org/show_bug.cgi?id=25523 Signed-off-by: Zhao Yakui Review-by: Jesse Barnes Tested-by: Hector Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 539d97ee79e..b3188a0b497 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -608,6 +608,13 @@ static const struct dmi_system_id bad_lid_status[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"), }, }, + { + .ident = "PC-81005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MALATA"), + DMI_MATCH(DMI_PRODUCT_NAME, "PC-81005"), + }, + }, { } }; -- cgit v1.2.3 From a2565377a5c31e25c77c7cabaf6752abe9a2d83a Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 11 Dec 2009 09:26:11 +0800 Subject: drm/i915: Update LVDS connector status when receiving ACPI LID event Dirk reports that nothing is displayed on LVDS when using ubuntu 9.1 after close/reopen the LID. And I also reproduce this issue on another laptop. After some tests and debug, it seems that it is related with that the LVDS status is not updated in time in course of suspend/resume. Now the LID state is used to check whether the LVDS is connected or disconnected. And when the LID is closed, it means that the LVDS is disconnected. When it is reopened, it means that the LVDS is connected. At the same time on some distributions the LID event is also used to put the system into suspend state. When the LID is closed, the system will enter the suspend state. When the LID is reopened, the system will be resumed. In such case when the LID is closed, user-space script will receive the LID notification event and detect the LVDS as disconnected. Then the system will enter the suspended state. When the LID is reopened, the system will be resumed. As the LVDS status is not updated in course of resume, it will cause that the LVDS connector is marked as unused and disabled. After the resume is finished,user-space script will try to configure the display mode for LVDS. But unfortunately as the LVDS status is not updated in time and it is still marked as disconnected, the LVDS and its corresponding CRTC will be disabled again in the function of drm_helper_disable_unused_functions after changing mode for LVDS. So we had better check and update the status of LVDS connector after receiving the LID notication event. Then after the system is resumed from suspended state, we can set the display mode for LVDS correctly. Signed-off-by: Zhao Yakui Reported-by: Dirk Hohndel Reviewed-by: Jesse Barnes CC: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_lvds.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fbecac72f5b..25c1047f6ec 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -561,6 +561,7 @@ typedef struct drm_i915_private { u16 orig_clock; int child_dev_num; struct child_device_config *child_dev; + struct drm_connector *int_lvds_connector; } drm_i915_private_t; /** driver private structure attached to each drm_gem_object */ diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b3188a0b497..f4b4aa242df 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -686,7 +686,14 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, struct drm_i915_private *dev_priv = container_of(nb, struct drm_i915_private, lid_notifier); struct drm_device *dev = dev_priv->dev; + struct drm_connector *connector = dev_priv->int_lvds_connector; + /* + * check and update the status of LVDS connector after receiving + * the LID nofication event. + */ + if (connector) + connector->status = connector->funcs->detect(connector); if (!acpi_lid_open()) { dev_priv->modeset_on_lid = 1; return NOTIFY_OK; @@ -1124,6 +1131,8 @@ out: DRM_DEBUG_KMS("lid notifier registration failed\n"); dev_priv->lid_notifier.notifier_call = NULL; } + /* keep the LVDS connector */ + dev_priv->int_lvds_connector = connector; drm_sysfs_connector_add(connector); return; -- cgit v1.2.3 From dc1a94ae1749d14c55f8b54e9d92bd89df82d51a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Nov 2009 16:35:54 +0100 Subject: PCI/PM: Propagate wake-up enable for PCIe devices too Having read the PM part of the PCIe 2.0 specification more carefully I think that it was a mistake to restrict the wake-up enable propagation to non-PCIe devices, because if we do not request control of the root ports' PME registers via OSC, PCIe PME is supposed to be handled by the platform, just like the non-PCIe PME. Even if we do that, the wake-up propagation is done to allow the devices to wake up the system from sleep states which involves the platform anyway, so it won't hurt. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index cc617ddd33d..7e2829538a4 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -112,11 +112,7 @@ static bool acpi_pci_can_wakeup(struct pci_dev *dev) static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) { while (bus->parent) { - struct pci_dev *bridge = bus->self; - int ret; - - ret = acpi_pm_device_sleep_wake(&bridge->dev, enable); - if (!ret || pci_is_pcie(bridge)) + if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable)) return; bus = bus->parent; } @@ -131,9 +127,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) if (acpi_pci_can_wakeup(dev)) return acpi_pm_device_sleep_wake(&dev->dev, enable); - if (!pci_is_pcie(dev)) - acpi_pci_propagate_wakeup_enable(dev->bus, enable); - + acpi_pci_propagate_wakeup_enable(dev->bus, enable); return 0; } -- cgit v1.2.3 From 2820f333e3b4ad96590093efbed7b3400bcf492b Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Tue, 15 Dec 2009 17:55:25 +0530 Subject: PCI: Handle case when no pci device can provide cache line size hint Prior to this patch, if pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, ...) returns 0 for all dev, pci_cache_line_size ends up set to zero (instead of pci_dfl_cache_line_size). This patch ensures the pci_cache_line_size = pci_dfl_cache_line_size setting in the above scenario. This happens in case of a kvm-88 guest (where, consequently, the rtl8139 NIC failed to initialize). Acked-by: Tejun Heo Signed-off-by: Csaba Henk Signed-off-by: Jesse Barnes --- drivers/pci/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7cfa7c38d31..f70f4e23225 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2629,7 +2629,7 @@ static int __init pci_apply_final_quirks(void) if (!pci_cache_line_size) { printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n", cls << 2, pci_dfl_cache_line_size << 2); - pci_cache_line_size = cls; + pci_cache_line_size = cls ? cls : pci_dfl_cache_line_size; } return 0; -- cgit v1.2.3 From b9c3b266411d27f1a6466c19d146d08db576bfea Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Mon, 7 Dec 2009 13:03:21 +0800 Subject: PCI: support device-specific reset methods Add a new type of quirk for resetting devices at pci_dev_reset time. This is necessary to handle device with nonstandard reset procedures, especially useful for guest drivers. Signed-off-by: Yu Zhao Signed-off-by: Dexuan Cui Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 19 +++++++++++++++++++ drivers/pci/pci.h | 8 ++++++++ drivers/pci/quirks.c | 9 +++++++++ 3 files changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0bc27e05901..6011d064e89 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2284,6 +2284,21 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) return 0; } +static int pci_dev_specific_reset(struct pci_dev *dev, int probe) +{ + struct pci_dev_reset_methods *i; + + for (i = pci_dev_reset_methods; i->reset; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) + return i->reset(dev, probe); + } + + return -ENOTTY; +} + static int pci_dev_reset(struct pci_dev *dev, int probe) { int rc; @@ -2296,6 +2311,10 @@ static int pci_dev_reset(struct pci_dev *dev, int probe) down(&dev->dev.sem); } + rc = pci_dev_specific_reset(dev, probe); + if (rc != -ENOTTY) + goto done; + rc = pcie_flr(dev, probe); if (rc != -ENOTTY) goto done; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 33ed8e0aba1..709eaa4fee5 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -313,4 +313,12 @@ static inline int pci_resource_alignment(struct pci_dev *dev, extern void pci_enable_acs(struct pci_dev *dev); +struct pci_dev_reset_methods { + u16 vendor; + u16 device; + int (*reset)(struct pci_dev *dev, int probe); +}; + +extern struct pci_dev_reset_methods pci_dev_reset_methods[]; + #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f70f4e23225..86c9177a6c6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2636,6 +2636,15 @@ static int __init pci_apply_final_quirks(void) } fs_initcall_sync(pci_apply_final_quirks); + +/* + * Followings are device-specific reset methods which can be used to + * reset a single function if other methods (e.g. FLR, PM D0->D3) are + * not available. + */ +struct pci_dev_reset_methods pci_dev_reset_methods[] = { + { 0 } +}; #else void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} #endif -- cgit v1.2.3 From aeb30016fec3378c543cae33654c2144277fe674 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Mon, 7 Dec 2009 13:03:22 +0800 Subject: PCI: add Intel USB specific reset method Handle device specific reset requirements (i.e. vendor reg for reset along with appropriate timeout). Signed-off-by: Yu Zhao Signed-off-by: Dexuan Cui Signed-off-by: Jesse Barnes --- drivers/pci/quirks.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 86c9177a6c6..cf96776d4bb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2642,7 +2642,31 @@ fs_initcall_sync(pci_apply_final_quirks); * reset a single function if other methods (e.g. FLR, PM D0->D3) are * not available. */ +static int reset_intel_generic_dev(struct pci_dev *dev, int probe) +{ + int pos; + + /* only implement PCI_CLASS_SERIAL_USB at present */ + if (dev->class == PCI_CLASS_SERIAL_USB) { + pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); + if (!pos) + return -ENOTTY; + + if (probe) + return 0; + + pci_write_config_byte(dev, pos + 0x4, 1); + msleep(100); + + return 0; + } else { + return -ENOTTY; + } +} + struct pci_dev_reset_methods pci_dev_reset_methods[] = { + { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, + reset_intel_generic_dev }, { 0 } }; #else -- cgit v1.2.3 From c763e7b58f71833e6cb7b05493eb1adda4811b08 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Mon, 7 Dec 2009 13:03:23 +0800 Subject: PCI: add Intel 82599 Virtual Function specific reset method Handle device specific timeout and use FLR. Signed-off-by: Yu Zhao Signed-off-by: Dexuan Cui Signed-off-by: Jesse Barnes --- drivers/pci/quirks.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index cf96776d4bb..8726698866b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2664,7 +2664,29 @@ static int reset_intel_generic_dev(struct pci_dev *dev, int probe) } } +static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) +{ + int pos; + + pos = pci_find_capability(dev, PCI_CAP_ID_EXP); + if (!pos) + return -ENOTTY; + + if (probe) + return 0; + + pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, + PCI_EXP_DEVCTL_BCR_FLR); + msleep(100); + + return 0; +} + +#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed + struct pci_dev_reset_methods pci_dev_reset_methods[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, + reset_intel_82599_sfp_virtfn }, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, reset_intel_generic_dev }, { 0 } -- cgit v1.2.3 From 45e829ea412760d2404d7dfc42528df46aedbf62 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Thu, 3 Dec 2009 06:49:24 -0500 Subject: PCI: change PCI nomenclature in drivers/pci/ (comment changes) Changing occurrences of variants of PCI-X and PCIe to the PCI-SIG terms listed in the "Trademark and Logo Usage Guidelines". http://www.pcisig.com/developers/procedures/logos/Trademark_and_Logo_Usage_Guidelines_updated_112206.pdf Patch is limited to drivers/pci/ and changes concern comments only. Signed-off-by: Stefan Assmann Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/shpchp.h | 2 +- drivers/pci/intel-iommu.c | 6 +++--- drivers/pci/intr_remapping.c | 2 +- drivers/pci/pci.c | 6 +++--- drivers/pci/pcie/aer/aer_inject.c | 4 ++-- drivers/pci/pcie/aer/aerdrv.c | 2 +- drivers/pci/pcie/aer/aerdrv_acpi.c | 2 +- drivers/pci/pcie/aer/aerdrv_core.c | 6 +++--- drivers/pci/pcie/aspm.c | 4 ++-- drivers/pci/search.c | 6 +++--- 10 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index bd588eb8e92..8e210cd76e5 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -121,7 +121,7 @@ struct controller { #define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458 -/* AMD PCIX bridge registers */ +/* AMD PCI-X bridge registers */ #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C #define PCIX_MISCII_OFFSET 0x48 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80 diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 8d615942631..25e15d518bd 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -304,7 +304,7 @@ struct device_domain_info { int segment; /* PCI domain */ u8 bus; /* PCI bus number */ u8 devfn; /* PCI devfn number */ - struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ + struct pci_dev *dev; /* it's NULL for PCIe-to-PCI bridge */ struct intel_iommu *iommu; /* IOMMU used by this device */ struct dmar_domain *domain; /* pointer to domain */ }; @@ -1611,7 +1611,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev, return ret; parent = parent->bus->self; } - if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */ + if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */ return domain_context_mapping_one(domain, pci_domain_nr(tmp->subordinate), tmp->subordinate->number, 0, @@ -3319,7 +3319,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu, parent->devfn); parent = parent->bus->self; } - if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */ + if (pci_is_pcie(tmp)) /* this is a PCIe-to-PCI bridge */ iommu_detach_dev(iommu, tmp->subordinate->number, 0); else /* this is a legacy PCI bridge */ diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index 1487bf2be86..c26caf18099 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c @@ -528,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev) bridge = pci_find_upstream_pcie_bridge(dev); if (bridge) { - if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */ + if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */ set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, (bridge->bus->number << 8) | dev->bus->number); else /* this is a legacy PCI bridge */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6011d064e89..d50522bf16b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1153,11 +1153,11 @@ pci_disable_device(struct pci_dev *dev) /** * pcibios_set_pcie_reset_state - set reset state for device dev - * @dev: the PCI-E device reset + * @dev: the PCIe device reset * @state: Reset state to enter into * * - * Sets the PCI-E reset state for the device. This is the default + * Sets the PCIe reset state for the device. This is the default * implementation. Architecture implementations can override this. */ int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev, @@ -1168,7 +1168,7 @@ int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev, /** * pci_set_pcie_reset_state - set reset state for device dev - * @dev: the PCI-E device reset + * @dev: the PCIe device reset * @state: Reset state to enter into * * diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 7fcd5331b14..0cae0f2b353 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -1,7 +1,7 @@ /* - * PCIE AER software error injection support. + * PCIe AER software error injection support. * - * Debuging PCIE AER code is quite difficult because it is hard to + * Debuging PCIe AER code is quite difficult because it is hard to * trigger various real hardware errors. Software based error * injection can fake almost all kinds of errors with the help of a * user space helper tool aer-inject, which can be gotten from: diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 97a345927b5..21f215f4daa 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -155,7 +155,7 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) mutex_init(&rpc->rpc_mutex); init_waitqueue_head(&rpc->wait_release); - /* Use PCIE bus function to store rpc into PCIE device */ + /* Use PCIe bus function to store rpc into PCIe device */ set_service_data(dev, rpc); return rpc; diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 8edb2f300e8..04814087658 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -24,7 +24,7 @@ * * @return: Zero on success. Nonzero otherwise. * - * Invoked when PCIE bus loads AER service driver. To avoid conflict with + * 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) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index ae672ca8033..c843a799814 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -587,7 +587,7 @@ static void handle_error_source(struct pcie_device *aerdev, * aer_enable_rootport - enable Root Port's interrupts when receiving messages * @rpc: pointer to a Root Port data structure * - * Invoked when PCIE bus loads AER service driver. + * Invoked when PCIe bus loads AER service driver. */ void aer_enable_rootport(struct aer_rpc *rpc) { @@ -597,7 +597,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) u32 reg32; pos = pci_pcie_cap(pdev); - /* Clear PCIE Capability's Device Status */ + /* Clear PCIe Capability's Device Status */ pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, ®16); pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16); @@ -631,7 +631,7 @@ void aer_enable_rootport(struct aer_rpc *rpc) * disable_root_aer - disable Root Port's interrupts when receiving messages * @rpc: pointer to a Root Port data structure * - * Invoked when PCIE bus unloads AER service driver. + * Invoked when PCIe bus unloads AER service driver. */ static void disable_root_aer(struct aer_rpc *rpc) { diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 5a01fc7fbf0..be53d98fa38 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1,6 +1,6 @@ /* * File: drivers/pci/pcie/aspm.c - * Enabling PCIE link L0s/L1 state and Clock Power Management + * Enabling PCIe link L0s/L1 state and Clock Power Management * * Copyright (C) 2007 Intel * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com) @@ -499,7 +499,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) int pos; u32 reg32; /* - * Some functions in a slot might not all be PCIE functions, + * Some functions in a slot might not all be PCIe functions, * very strange. Disable ASPM for the whole slot */ list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 6dae8714325..4a471dc4f4b 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -15,9 +15,9 @@ DECLARE_RWSEM(pci_bus_sem); /* - * find the upstream PCIE-to-PCI bridge of a PCI device + * find the upstream PCIe-to-PCI bridge of a PCI device * if the device is PCIE, return NULL - * if the device isn't connected to a PCIE bridge (that is its parent is a + * if the device isn't connected to a PCIe bridge (that is its parent is a * legacy PCI bridge and the bridge is directly connected to bus 0), return its * parent */ @@ -37,7 +37,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) tmp = pdev; continue; } - /* PCI device should connect to a PCIE bridge */ + /* PCI device should connect to a PCIe bridge */ if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) { /* Busted hardware? */ WARN_ON_ONCE(1); -- cgit v1.2.3 From 7e8af37a9a71b479f58d2fd5f0ddaa6780c51f11 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Thu, 3 Dec 2009 18:00:10 +0100 Subject: PCI: change PCI nomenclature in drivers/pci/ (non-comment changes) Changing occurrences of variants of PCI-X and PCIe to the PCI-SIG terms listed in the "Trademark and Logo Usage Guidelines". http://www.pcisig.com/developers/procedures/logos/Trademark_and_Logo_Usage_Guidelines_updated_112206.pdf Patch is limited to drivers/pci/ and changes concern non-comment parts or anything that might be visible to the user. Signed-off-by: Stefan Assmann Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/Kconfig.debug | 4 ++-- drivers/pci/pcie/aer/aer_inject.c | 2 +- drivers/pci/pcie/aer/aerdrv_errprint.c | 4 ++-- drivers/pci/pcie/portdrv_pci.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/Kconfig.debug b/drivers/pci/pcie/aer/Kconfig.debug index b8c925c1f6a..9142949734f 100644 --- a/drivers/pci/pcie/aer/Kconfig.debug +++ b/drivers/pci/pcie/aer/Kconfig.debug @@ -3,14 +3,14 @@ # config PCIEAER_INJECT - tristate "PCIE AER error injector support" + tristate "PCIe AER error injector support" depends on PCIEAER default n help This enables PCI Express Root Port Advanced Error Reporting (AER) software error injector. - Debuging PCIE AER code is quite difficult because it is hard + Debugging PCIe AER code is quite difficult because it is hard to trigger various real hardware errors. Software based error injection can fake almost all kinds of errors with the help of a user space helper tool aer-inject, which can be diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 0cae0f2b353..797d47809f7 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -484,5 +484,5 @@ static void __exit aer_inject_exit(void) module_init(aer_inject_init); module_exit(aer_inject_exit); -MODULE_DESCRIPTION("PCIE AER software error injector"); +MODULE_DESCRIPTION("PCIe AER software error injector"); MODULE_LICENSE("GPL"); diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 44acde72294..9d3e4c8d018 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -184,7 +184,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) if (info->status == 0) { AER_PR(info, dev, - "PCIE Bus Error: severity=%s, type=Unaccessible, " + "PCIe Bus Error: severity=%s, type=Unaccessible, " "id=%04x(Unregistered Agent ID)\n", aer_error_severity_string[info->severity], id); } else { @@ -194,7 +194,7 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) agent = AER_GET_AGENT(info->severity, info->status); AER_PR(info, dev, - "PCIE Bus Error: severity=%s, type=%s, id=%04x(%s)\n", + "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", aer_error_severity_string[info->severity], aer_error_layer[layer], id, aer_agent_string[agent]); diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index a49452e2aed..34d65172a4d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -24,7 +24,7 @@ */ #define DRIVER_VERSION "v1.0" #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" -#define DRIVER_DESC "PCIE Port Bus Driver" +#define DRIVER_DESC "PCIe Port Bus Driver" MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 49ae35f2dd1ff78ee88d5f8a38d0af63c3ad9f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 16 Dec 2009 15:16:15 -0500 Subject: drm/i915: Move PCI IDs into i915 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old include/drm/drm_pciids.h used to be generated from the libdrm git repo. We don't use that anymore so just use a local list in the driver like everybody else. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 42 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6978a22f70e..b6ec949361e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -33,7 +33,6 @@ #include "i915_drm.h" #include "i915_drv.h" -#include "drm_pciids.h" #include #include "drm_crtc_helper.h" @@ -48,8 +47,47 @@ module_param_named(powersave, i915_powersave, int, 0400); static struct drm_driver driver; +#define INTEL_VGA_DEVICE(id) { \ + .class = PCI_CLASS_DISPLAY_VGA << 8, \ + .class_mask = 0xffff00, \ + .vendor = 0x8086, \ + .device = id, \ + .subvendor = PCI_ANY_ID, \ + .subdevice = PCI_ANY_ID, \ + .driver_data = 0 } + static struct pci_device_id pciidlist[] = { - i915_PCI_IDS + INTEL_VGA_DEVICE(0x3577), + INTEL_VGA_DEVICE(0x2562), + INTEL_VGA_DEVICE(0x3582), + INTEL_VGA_DEVICE(0x2572), + INTEL_VGA_DEVICE(0x2582), + INTEL_VGA_DEVICE(0x258a), + INTEL_VGA_DEVICE(0x2592), + INTEL_VGA_DEVICE(0x2772), + INTEL_VGA_DEVICE(0x27a2), + INTEL_VGA_DEVICE(0x27ae), + INTEL_VGA_DEVICE(0x2972), + INTEL_VGA_DEVICE(0x2982), + INTEL_VGA_DEVICE(0x2992), + INTEL_VGA_DEVICE(0x29a2), + INTEL_VGA_DEVICE(0x29b2), + INTEL_VGA_DEVICE(0x29c2), + INTEL_VGA_DEVICE(0x29d2), + INTEL_VGA_DEVICE(0x2a02), + INTEL_VGA_DEVICE(0x2a12), + INTEL_VGA_DEVICE(0x2a42), + INTEL_VGA_DEVICE(0x2e02), + INTEL_VGA_DEVICE(0x2e12), + INTEL_VGA_DEVICE(0x2e22), + INTEL_VGA_DEVICE(0x2e32), + INTEL_VGA_DEVICE(0x2e42), + INTEL_VGA_DEVICE(0xa001), + INTEL_VGA_DEVICE(0xa011), + INTEL_VGA_DEVICE(0x35e8), + INTEL_VGA_DEVICE(0x0042), + INTEL_VGA_DEVICE(0x0046), + {0, 0, 0} }; #if defined(CONFIG_DRM_I915_KMS) -- cgit v1.2.3 From cfdf1fa23f4074c9f8766dc67a928bbf680b1ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 16 Dec 2009 15:16:16 -0500 Subject: drm/i915: Implement IS_* macros using static tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using the IS_I9XX etc macros that expand to a ton of comparisons, use new struct intel_device_info to capture the capabilities of the different chipsets. The drm_i915_private struct will be initialized to point to the device info that correspond to the actual device and this way, testing for a specific capability is just a matter of checking a bit field. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 4 +- drivers/gpu/drm/i915/i915_drv.c | 144 ++++++++++++++++++++++++++++++---------- drivers/gpu/drm/i915/i915_drv.h | 112 ++++++++++++++----------------- 3 files changed, 161 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 701bfeac7f5..549e46c1a97 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1360,7 +1360,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv = dev->dev_private; resource_size_t base, size; - int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; + int ret = 0, mmio_bar; uint32_t agp_size, prealloc_size, prealloc_start; /* i915 has 4 more counters */ @@ -1376,8 +1376,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->dev_private = (void *)dev_priv; dev_priv->dev = dev; + dev_priv->info = (struct intel_device_info *) flags; /* Add register map (needed for suspend/resume) */ + mmio_bar = IS_I9XX(dev) ? 0 : 1; base = drm_get_resource_start(dev, mmio_bar); size = drm_get_resource_len(dev, mmio_bar); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b6ec949361e..1b256de2456 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -47,46 +47,122 @@ module_param_named(powersave, i915_powersave, int, 0400); static struct drm_driver driver; -#define INTEL_VGA_DEVICE(id) { \ +#define INTEL_VGA_DEVICE(id, info) { \ .class = PCI_CLASS_DISPLAY_VGA << 8, \ .class_mask = 0xffff00, \ .vendor = 0x8086, \ .device = id, \ .subvendor = PCI_ANY_ID, \ .subdevice = PCI_ANY_ID, \ - .driver_data = 0 } - -static struct pci_device_id pciidlist[] = { - INTEL_VGA_DEVICE(0x3577), - INTEL_VGA_DEVICE(0x2562), - INTEL_VGA_DEVICE(0x3582), - INTEL_VGA_DEVICE(0x2572), - INTEL_VGA_DEVICE(0x2582), - INTEL_VGA_DEVICE(0x258a), - INTEL_VGA_DEVICE(0x2592), - INTEL_VGA_DEVICE(0x2772), - INTEL_VGA_DEVICE(0x27a2), - INTEL_VGA_DEVICE(0x27ae), - INTEL_VGA_DEVICE(0x2972), - INTEL_VGA_DEVICE(0x2982), - INTEL_VGA_DEVICE(0x2992), - INTEL_VGA_DEVICE(0x29a2), - INTEL_VGA_DEVICE(0x29b2), - INTEL_VGA_DEVICE(0x29c2), - INTEL_VGA_DEVICE(0x29d2), - INTEL_VGA_DEVICE(0x2a02), - INTEL_VGA_DEVICE(0x2a12), - INTEL_VGA_DEVICE(0x2a42), - INTEL_VGA_DEVICE(0x2e02), - INTEL_VGA_DEVICE(0x2e12), - INTEL_VGA_DEVICE(0x2e22), - INTEL_VGA_DEVICE(0x2e32), - INTEL_VGA_DEVICE(0x2e42), - INTEL_VGA_DEVICE(0xa001), - INTEL_VGA_DEVICE(0xa011), - INTEL_VGA_DEVICE(0x35e8), - INTEL_VGA_DEVICE(0x0042), - INTEL_VGA_DEVICE(0x0046), + .driver_data = (unsigned long) info } + +const static struct intel_device_info intel_i830_info = { + .is_i8xx = 1, .is_mobile = 1, +}; + +const static struct intel_device_info intel_845g_info = { + .is_i8xx = 1, +}; + +const static struct intel_device_info intel_i85x_info = { + .is_i8xx = 1, .is_mobile = 1, +}; + +const static struct intel_device_info intel_i865g_info = { + .is_i8xx = 1, +}; + +const static struct intel_device_info intel_i915g_info = { + .is_i915g = 1, .is_i9xx = 1, +}; +const static struct intel_device_info intel_i915gm_info = { + .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, +}; +const static struct intel_device_info intel_i945g_info = { + .is_i9xx = 1, .has_hotplug = 1, +}; +const static struct intel_device_info intel_i945gm_info = { + .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_i965g_info = { + .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1, +}; + +const static struct intel_device_info intel_i965gm_info = { + .is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1, + .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, + .has_hotplug = 1, +}; + +const static struct intel_device_info intel_g33_info = { + .is_g33 = 1, .is_i9xx = 1, .need_gfx_hws = 1, + .has_hotplug = 1, +}; + +const static 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, +}; + +const static struct intel_device_info intel_gm45_info = { + .is_i965g = 1, .is_mobile = 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, +}; + +const static struct intel_device_info intel_pineview_info = { + .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .is_i9xx = 1, + .has_pipe_cxsr = 1, + .has_hotplug = 1, +}; + +const static 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, +}; + +const static 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_rc6 = 1, + .has_hotplug = 1, +}; + +const static struct pci_device_id pciidlist[] = { + INTEL_VGA_DEVICE(0x3577, &intel_i830_info), + INTEL_VGA_DEVICE(0x2562, &intel_845g_info), + INTEL_VGA_DEVICE(0x3582, &intel_i85x_info), + INTEL_VGA_DEVICE(0x35e8, &intel_i85x_info), + INTEL_VGA_DEVICE(0x2572, &intel_i865g_info), + INTEL_VGA_DEVICE(0x2582, &intel_i915g_info), + INTEL_VGA_DEVICE(0x258a, &intel_i915g_info), + INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info), + INTEL_VGA_DEVICE(0x2772, &intel_i945g_info), + INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info), + INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info), + INTEL_VGA_DEVICE(0x2972, &intel_i965g_info), + INTEL_VGA_DEVICE(0x2982, &intel_i965g_info), + INTEL_VGA_DEVICE(0x2992, &intel_i965g_info), + INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info), + INTEL_VGA_DEVICE(0x29b2, &intel_g33_info), + INTEL_VGA_DEVICE(0x29c2, &intel_g33_info), + INTEL_VGA_DEVICE(0x29d2, &intel_g33_info), + INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info), + INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info), + INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info), + INTEL_VGA_DEVICE(0x2e02, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e12, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e22, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e32, &intel_g45_info), + INTEL_VGA_DEVICE(0x2e42, &intel_g45_info), + 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), {0, 0, 0} }; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 25c1047f6ec..0d24e034dc2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -172,9 +172,30 @@ struct drm_i915_display_funcs { struct intel_overlay; +struct intel_device_info { + u8 is_mobile : 1; + u8 is_i8xx : 1; + u8 is_i915g : 1; + u8 is_i9xx : 1; + u8 is_i945gm : 1; + u8 is_i965g : 1; + u8 is_i965gm : 1; + u8 is_g33 : 1; + u8 need_gfx_hws : 1; + u8 is_g4x : 1; + u8 is_pineview : 1; + u8 is_ironlake : 1; + u8 has_fbc : 1; + u8 has_rc6 : 1; + u8 has_pipe_cxsr : 1; + u8 has_hotplug : 1; +}; + typedef struct drm_i915_private { struct drm_device *dev; + const struct intel_device_info *info; + int has_gem; void __iomem *regs; @@ -983,67 +1004,33 @@ extern void g4x_disable_fbc(struct drm_device *dev); extern int i915_wrap_ring(struct drm_device * dev); extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); -#define IS_I830(dev) ((dev)->pci_device == 0x3577) -#define IS_845G(dev) ((dev)->pci_device == 0x2562) -#define IS_I85X(dev) ((dev)->pci_device == 0x3582) -#define IS_I865G(dev) ((dev)->pci_device == 0x2572) -#define IS_I8XX(dev) (IS_I830(dev) || IS_845G(dev) || IS_I85X(dev) || IS_I865G(dev)) - -#define IS_I915G(dev) ((dev)->pci_device == 0x2582 || (dev)->pci_device == 0x258a) -#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) -#define IS_I945G(dev) ((dev)->pci_device == 0x2772) -#define IS_I945GM(dev) ((dev)->pci_device == 0x27A2 ||\ - (dev)->pci_device == 0x27AE) -#define IS_I965G(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 == 0x2A42 || \ - (dev)->pci_device == 0x2E02 || \ - (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22 || \ - (dev)->pci_device == 0x2E32 || \ - (dev)->pci_device == 0x2E42 || \ - (dev)->pci_device == 0x0042 || \ - (dev)->pci_device == 0x0046) - -#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02 || \ - (dev)->pci_device == 0x2A12) - -#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) - -#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \ - (dev)->pci_device == 0x2E12 || \ - (dev)->pci_device == 0x2E22 || \ - (dev)->pci_device == 0x2E32 || \ - (dev)->pci_device == 0x2E42 || \ - IS_GM45(dev)) - -#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) -#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) -#define IS_PINEVIEW(dev) (IS_PINEVIEW_G(dev) || IS_PINEVIEW_M(dev)) - -#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \ - (dev)->pci_device == 0x29B2 || \ - (dev)->pci_device == 0x29D2 || \ - (IS_PINEVIEW(dev))) - +#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) + +#define IS_I830(dev) ((dev)->pci_device == 0x3577) +#define IS_845G(dev) ((dev)->pci_device == 0x2562) +#define IS_I85X(dev) ((dev)->pci_device == 0x3582) +#define IS_I865G(dev) ((dev)->pci_device == 0x2572) +#define IS_I8XX(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) +#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) +#define IS_I965G(dev) (INTEL_INFO(dev)->is_i965g) +#define IS_I965GM(dev) (INTEL_INFO(dev)->is_i965gm) +#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) +#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) +#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) +#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) +#define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) +#define IS_G33(dev) (INTEL_INFO(dev)->is_g33) #define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) #define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) -#define IS_IRONLAKE(dev) (IS_IRONLAKE_D(dev) || IS_IRONLAKE_M(dev)) - -#define IS_I9XX(dev) (IS_I915G(dev) || IS_I915GM(dev) || IS_I945G(dev) || \ - IS_I945GM(dev) || IS_I965G(dev) || IS_G33(dev) || \ - IS_IRONLAKE(dev)) +#define IS_IRONLAKE(dev) (INTEL_INFO(dev)->is_ironlake) +#define IS_I9XX(dev) (INTEL_INFO(dev)->is_i9xx) +#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) -#define IS_MOBILE(dev) (IS_I830(dev) || IS_I85X(dev) || IS_I915GM(dev) || \ - IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev) || \ - IS_PINEVIEW(dev) || IS_IRONLAKE_M(dev)) +#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) -#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev) || \ - IS_IRONLAKE(dev)) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. */ @@ -1055,17 +1042,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) #define SUPPORTS_TV(dev) (IS_I9XX(dev) && IS_MOBILE(dev) && \ !IS_IRONLAKE(dev) && !IS_PINEVIEW(dev)) -#define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev) || IS_I965G(dev)) +#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) /* dsparb controlled by hw only */ #define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) #define HAS_FW_BLC(dev) (IS_I9XX(dev) || IS_G4X(dev) || IS_IRONLAKE(dev)) -#define HAS_PIPE_CXSR(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) -#define I915_HAS_FBC(dev) (IS_MOBILE(dev) && \ - (IS_I9XX(dev) || IS_GM45(dev)) && \ - !IS_PINEVIEW(dev) && \ - !IS_IRONLAKE(dev)) -#define I915_HAS_RC6(dev) (IS_I965GM(dev) || IS_GM45(dev) || IS_IRONLAKE_M(dev)) +#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) +#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) +#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) #define PRIMARY_RINGBUFFER_SIZE (128*1024) -- cgit v1.2.3 From b295d1b6e3e3f240d27cbe556d33ff5eb54721a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 16 Dec 2009 15:16:17 -0500 Subject: drm/i915: Track whether cursor needs physical address in intel_device_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 8 -------- drivers/gpu/drm/i915/i915_drv.c | 11 ++++++----- drivers/gpu/drm/i915/i915_drv.h | 3 +-- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 549e46c1a97..28d99b8a049 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1200,14 +1200,6 @@ static int i915_load_modeset_init(struct drm_device *dev, dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & 0xff000000; - if (IS_MOBILE(dev) || IS_I9XX(dev)) - dev_priv->cursor_needs_physical = true; - else - dev_priv->cursor_needs_physical = false; - - if (IS_I965G(dev) || IS_G33(dev)) - dev_priv->cursor_needs_physical = false; - /* Basic memrange allocator for stolen space (aka vram) */ drm_mm_init(&dev_priv->vram, 0, prealloc_size); DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024)); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1b256de2456..a0a2cad8c01 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -57,7 +57,7 @@ static struct drm_driver driver; .driver_data = (unsigned long) info } const static struct intel_device_info intel_i830_info = { - .is_i8xx = 1, .is_mobile = 1, + .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_845g_info = { @@ -65,7 +65,7 @@ const static struct intel_device_info intel_845g_info = { }; const static struct intel_device_info intel_i85x_info = { - .is_i8xx = 1, .is_mobile = 1, + .is_i8xx = 1, .is_mobile = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i865g_info = { @@ -73,17 +73,18 @@ const static struct intel_device_info intel_i865g_info = { }; const static struct intel_device_info intel_i915g_info = { - .is_i915g = 1, .is_i9xx = 1, + .is_i915g = 1, .is_i9xx = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i915gm_info = { .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, + .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i945g_info = { - .is_i9xx = 1, .has_hotplug = 1, + .is_i9xx = 1, .has_hotplug = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i945gm_info = { .is_i945gm = 1, .is_i9xx = 1, .is_mobile = 1, .has_fbc = 1, - .has_hotplug = 1, + .has_hotplug = 1, .cursor_needs_physical = 1, }; const static struct intel_device_info intel_i965g_info = { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0d24e034dc2..9a05f1a0102 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -189,6 +189,7 @@ struct intel_device_info { u8 has_rc6 : 1; u8 has_pipe_cxsr : 1; u8 has_hotplug : 1; + u8 cursor_needs_physical : 1; }; typedef struct drm_i915_private { @@ -253,8 +254,6 @@ typedef struct drm_i915_private { int hangcheck_count; uint32_t last_acthd; - bool cursor_needs_physical; - struct drm_mm vram; unsigned long cfb_size; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 52cd9b006da..ef9c6139ee3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3385,7 +3385,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, /* we only need to pin inside GTT if cursor is non-phy */ mutex_lock(&dev->struct_mutex); - if (!dev_priv->cursor_needs_physical) { + if (!dev_priv->info->cursor_needs_physical) { ret = i915_gem_object_pin(bo, PAGE_SIZE); if (ret) { DRM_ERROR("failed to pin cursor bo\n"); @@ -3420,7 +3420,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc, I915_WRITE(base, addr); if (intel_crtc->cursor_bo) { - if (dev_priv->cursor_needs_physical) { + if (dev_priv->info->cursor_needs_physical) { if (intel_crtc->cursor_bo != bo) i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); } else -- cgit v1.2.3 From b01f2c3a4a37d09a47ad73ccbb46d554d21cfeb0 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 11 Dec 2009 11:07:17 -0800 Subject: drm/i915: only enable hotplug for detected outputs This patch changes around our hotplug enable code a bit to only enable it for ports we actually detect and initialize. This prevents problems with stuck or spurious interrupts on outputs that aren't actually wired up, and is generally more correct. Fixes FDO bug #23183. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 30 +++++++++++++++++++----------- drivers/gpu/drm/i915/i915_reg.h | 7 ------- drivers/gpu/drm/i915/intel_crt.c | 2 ++ drivers/gpu/drm/i915/intel_display.c | 26 ++++++++++++++++++++------ drivers/gpu/drm/i915/intel_dp.c | 6 ++++++ drivers/gpu/drm/i915/intel_hdmi.c | 5 +++++ drivers/gpu/drm/i915/intel_sdvo.c | 3 +++ drivers/gpu/drm/i915/intel_tv.c | 2 ++ 9 files changed, 59 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 28d99b8a049..e3e5d509423 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1249,6 +1249,8 @@ static int i915_load_modeset_init(struct drm_device *dev, if (ret) goto destroy_ringbuffer; + intel_modeset_init(dev); + ret = drm_irq_install(dev); if (ret) goto destroy_ringbuffer; @@ -1263,8 +1265,6 @@ static int i915_load_modeset_init(struct drm_device *dev, I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); - intel_modeset_init(dev); - drm_helper_initial_config(dev); return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 85f4c5de97e..1733eea8784 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1084,6 +1084,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) (void) I915_READ(IER); } +/* + * Must be called after intel_modeset_init or hotplug interrupts won't be + * enabled correctly. + */ int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1106,19 +1110,23 @@ int i915_driver_irq_postinstall(struct drm_device *dev) if (I915_HAS_HOTPLUG(dev)) { u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); - /* Leave other bits alone */ - hotplug_en |= HOTPLUG_EN_MASK; + /* Note HDMI and DP share bits */ + if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) + hotplug_en |= HDMIC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) + hotplug_en |= HDMID_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) + hotplug_en |= CRT_HOTPLUG_INT_EN; + /* Ignore TV since it's buggy */ + I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - dev_priv->hotplug_supported_mask = CRT_HOTPLUG_INT_STATUS | - TV_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS | - SDVOB_HOTPLUG_INT_STATUS; - if (IS_G4X(dev)) { - dev_priv->hotplug_supported_mask |= - HDMIB_HOTPLUG_INT_STATUS | - HDMIC_HOTPLUG_INT_STATUS | - HDMID_HOTPLUG_INT_STATUS; - } /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 974b3cf7061..f79b13324fa 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -879,13 +879,6 @@ #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) #define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ #define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f -#define HOTPLUG_EN_MASK (HDMIB_HOTPLUG_INT_EN | \ - HDMIC_HOTPLUG_INT_EN | \ - HDMID_HOTPLUG_INT_EN | \ - SDVOB_HOTPLUG_INT_EN | \ - SDVOC_HOTPLUG_INT_EN | \ - CRT_HOTPLUG_INT_EN) - #define PORT_HOTPLUG_STAT 0x61114 #define HDMIB_HOTPLUG_INT_STATUS (1 << 29) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 9f3d3e56341..ddefc871edf 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -548,4 +548,6 @@ void intel_crt_init(struct drm_device *dev) drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); drm_sysfs_connector_add(connector); + + dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ef9c6139ee3..c21dede6461 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4400,29 +4400,43 @@ static void intel_setup_outputs(struct drm_device *dev) bool found = false; if (I915_READ(SDVOB) & SDVO_DETECTED) { + DRM_DEBUG_KMS("probing SDVOB\n"); found = intel_sdvo_init(dev, SDVOB); - if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) + if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) { + DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); intel_hdmi_init(dev, SDVOB); + } - if (!found && SUPPORTS_INTEGRATED_DP(dev)) + if (!found && SUPPORTS_INTEGRATED_DP(dev)) { + DRM_DEBUG_KMS("probing DP_B\n"); intel_dp_init(dev, DP_B); + } } /* Before G4X SDVOC doesn't have its own detect register */ - if (I915_READ(SDVOB) & SDVO_DETECTED) + if (I915_READ(SDVOB) & SDVO_DETECTED) { + DRM_DEBUG_KMS("probing SDVOC\n"); found = intel_sdvo_init(dev, SDVOC); + } if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) { - if (SUPPORTS_INTEGRATED_HDMI(dev)) + if (SUPPORTS_INTEGRATED_HDMI(dev)) { + DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); intel_hdmi_init(dev, SDVOC); - if (SUPPORTS_INTEGRATED_DP(dev)) + } + if (SUPPORTS_INTEGRATED_DP(dev)) { + DRM_DEBUG_KMS("probing DP_C\n"); intel_dp_init(dev, DP_C); + } } - if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) + if (SUPPORTS_INTEGRATED_DP(dev) && + (I915_READ(DP_D) & DP_DETECTED)) { + DRM_DEBUG_KMS("probing DP_D\n"); intel_dp_init(dev, DP_D); + } } else if (IS_I8XX(dev)) intel_dvo_init(dev); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4e7aa8b7b93..1349d9fd01c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1402,14 +1402,20 @@ intel_dp_init(struct drm_device *dev, int output_reg) break; case DP_B: case PCH_DP_B: + dev_priv->hotplug_supported_mask |= + HDMIB_HOTPLUG_INT_STATUS; name = "DPDDC-B"; break; case DP_C: case PCH_DP_C: + dev_priv->hotplug_supported_mask |= + HDMIC_HOTPLUG_INT_STATUS; name = "DPDDC-C"; break; case DP_D: case PCH_DP_D: + dev_priv->hotplug_supported_mask |= + HDMID_HOTPLUG_INT_STATUS; name = "DPDDC-D"; break; } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index f04dbbe7d40..06431941b23 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -303,21 +303,26 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (sdvox_reg == SDVOB) { intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); + dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; } else if (sdvox_reg == SDVOC) { intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); + dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMIB) { intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, "HDMIB"); + dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMIC) { intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, "HDMIC"); + dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS; } else if (sdvox_reg == HDMID) { intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, "HDMID"); + dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS; } if (!intel_output->ddc_bus) goto err_connector; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 24a3dc99716..de5144c8c15 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2662,6 +2662,7 @@ static void intel_sdvo_create_enhance_property(struct drm_connector *connector) bool intel_sdvo_init(struct drm_device *dev, int output_device) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_connector *connector; struct intel_output *intel_output; struct intel_sdvo_priv *sdvo_priv; @@ -2708,10 +2709,12 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOB/VGA DDC BUS"); + dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; } else { intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); sdvo_priv->analog_ddc_bus = intel_i2c_create(dev, GPIOA, "SDVOC/VGA DDC BUS"); + dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; } if (intel_output->ddc_bus == NULL) diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 552ec110b74..1d5b9b7b033 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1840,6 +1840,8 @@ intel_tv_init(struct drm_device *dev) drm_connector_attach_property(connector, dev->mode_config.tv_bottom_margin_property, tv_priv->margin[TV_MARGIN_BOTTOM]); + + dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; out: drm_sysfs_connector_add(connector); } -- cgit v1.2.3 From 2d1c861871d767153538a77c498752b36d4bb4b8 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 9 Dec 2009 17:52:13 +1100 Subject: PCI/cardbus: Add a fixup hook and fix powerpc The cardbus code creates PCI devices without ever going through the necessary fixup bits and pieces that normal PCI devices go through. There's in fact a commented out call to pcibios_fixup_bus() in there, it's commented because ... it doesn't work. I could make pcibios_fixup_bus() do the right thing on powerpc easily but I felt it cleaner instead to provide a specific hook pci_fixup_cardbus for which a weak empty implementation is provided by the PCI core. This fixes cardbus on powerbooks and probably all other PowerPC platforms which was broken completely for ever on some platforms and since 2.6.31 on others such as PowerBooks when we made the DMA ops mandatory (since those are setup by the fixups). Acked-by: Dominik Brodowski Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 5 +++++ drivers/pcmcia/cardbus.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d50522bf16b..864e703cf73 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2798,6 +2798,11 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev) return 1; } +void __weak pci_fixup_cardbus(struct pci_bus *bus) +{ +} +EXPORT_SYMBOL(pci_fixup_cardbus); + static int __init pci_setup(char *str) { while (str) { diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index cdf50f3bc2d..d99f846451a 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -222,7 +222,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) unsigned int max, pass; s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); -/* pcibios_fixup_bus(bus); */ + pci_fixup_cardbus(bus); max = bus->secondary; for (pass = 0; pass < 2; pass++) -- cgit v1.2.3 From 4f924ba5b5aaf1477daafeae779495d39549186d Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 17 Dec 2009 00:08:33 +0900 Subject: sony-laptop: add AVMode key mapping Some models are equipped with an "AVMode" function key that sends sony-laptop: Unknown event: 0x100 0xa1 sony-laptop: Unknown event: 0x100 0x21 for press and release respectively. Cc: "Matthew W. S. Bell" Cc: Dmitry Torokhov Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index a2a742c8ff7..9710f70040b 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -232,6 +232,7 @@ static int sony_laptop_input_index[] = { 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ + 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ }; static int sony_laptop_input_keycode_map[] = { @@ -293,6 +294,7 @@ static int sony_laptop_input_keycode_map[] = { KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ + KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ }; /* release buttons after a short delay if pressed */ @@ -890,6 +892,8 @@ static struct sony_nc_event sony_100_events[] = { { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, + { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }, }; -- cgit v1.2.3 From 3542a113ab2f5880f1b62e5909d754250fb57d6b Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 17 Dec 2009 09:41:39 -0700 Subject: sh: fix DMA driver's descriptor chaining and cookie assignment The SH DMA driver wrongly assigns negative cookies to transfer descriptors, also, its chaining of partial descriptors is broken. The latter problem is usually invisible, because maximum transfer size per chunk is 16M, but if you artificially set this limit lower, the driver fails. Since cookies are also used in chunk management, both these problems are fixed in one patch. As side effects a possible memory leak, when descriptors are prepared, but not submitted, and multiple races have also been fixed. Signed-off-by: Guennadi Liakhovetski Acked-by: Paul Mundt Acked-by: Nobuhiro Iwamatsu Signed-off-by: Dan Williams --- drivers/dma/shdma.c | 324 +++++++++++++++++++++++++++++++++------------------- drivers/dma/shdma.h | 9 +- 2 files changed, 213 insertions(+), 120 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 8d9acd751ed..9546f5f356e 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -23,16 +23,19 @@ #include #include #include -#include #include #include #include #include "shdma.h" /* DMA descriptor control */ -#define DESC_LAST (-1) -#define DESC_COMP (1) -#define DESC_NCOMP (0) +enum sh_dmae_desc_status { + DESC_IDLE, + DESC_PREPARED, + DESC_SUBMITTED, + DESC_COMPLETED, /* completed, have to call callback */ + DESC_WAITING, /* callback called, waiting for ack / re-submit */ +}; #define NR_DESCS_PER_CHANNEL 32 /* @@ -45,6 +48,8 @@ */ #define RS_DEFAULT (RS_DUAL) +static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); + #define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id]) static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg) { @@ -106,11 +111,11 @@ static inline unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan) return ts_shift[(chcr & CHCR_TS_MASK) >> CHCR_TS_SHIFT]; } -static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs hw) +static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw) { - sh_dmae_writel(sh_chan, hw.sar, SAR); - sh_dmae_writel(sh_chan, hw.dar, DAR); - sh_dmae_writel(sh_chan, hw.tcr >> calc_xmit_shift(sh_chan), TCR); + sh_dmae_writel(sh_chan, hw->sar, SAR); + sh_dmae_writel(sh_chan, hw->dar, DAR); + sh_dmae_writel(sh_chan, hw->tcr >> calc_xmit_shift(sh_chan), TCR); } static void dmae_start(struct sh_dmae_chan *sh_chan) @@ -184,8 +189,9 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) { - struct sh_desc *desc = tx_to_sh_desc(tx); + struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c; struct sh_dmae_chan *sh_chan = to_sh_chan(tx->chan); + dma_async_tx_callback callback = tx->callback; dma_cookie_t cookie; spin_lock_bh(&sh_chan->desc_lock); @@ -195,45 +201,53 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx) if (cookie < 0) cookie = 1; - /* If desc only in the case of 1 */ - if (desc->async_tx.cookie != -EBUSY) - desc->async_tx.cookie = cookie; - sh_chan->common.cookie = desc->async_tx.cookie; + sh_chan->common.cookie = cookie; + tx->cookie = cookie; + + /* Mark all chunks of this descriptor as submitted, move to the queue */ + list_for_each_entry_safe(chunk, c, desc->node.prev, node) { + /* + * All chunks are on the global ld_free, so, we have to find + * the end of the chain ourselves + */ + if (chunk != desc && (chunk->mark == DESC_IDLE || + chunk->async_tx.cookie > 0 || + chunk->async_tx.cookie == -EBUSY || + &chunk->node == &sh_chan->ld_free)) + break; + chunk->mark = DESC_SUBMITTED; + /* Callback goes to the last chunk */ + chunk->async_tx.callback = NULL; + chunk->cookie = cookie; + list_move_tail(&chunk->node, &sh_chan->ld_queue); + last = chunk; + } + + last->async_tx.callback = callback; + last->async_tx.callback_param = tx->callback_param; - list_splice_init(&desc->tx_list, sh_chan->ld_queue.prev); + dev_dbg(sh_chan->dev, "submit #%d@%p on %d: %x[%d] -> %x\n", + tx->cookie, &last->async_tx, sh_chan->id, + desc->hw.sar, desc->hw.tcr, desc->hw.dar); spin_unlock_bh(&sh_chan->desc_lock); return cookie; } +/* Called with desc_lock held */ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) { - struct sh_desc *desc, *_desc, *ret = NULL; + struct sh_desc *desc; - spin_lock_bh(&sh_chan->desc_lock); - list_for_each_entry_safe(desc, _desc, &sh_chan->ld_free, node) { - if (async_tx_test_ack(&desc->async_tx)) { + list_for_each_entry(desc, &sh_chan->ld_free, node) + if (desc->mark != DESC_PREPARED) { + BUG_ON(desc->mark != DESC_IDLE); list_del(&desc->node); - ret = desc; - break; + return desc; } - } - spin_unlock_bh(&sh_chan->desc_lock); - - return ret; -} - -static void sh_dmae_put_desc(struct sh_dmae_chan *sh_chan, struct sh_desc *desc) -{ - if (desc) { - spin_lock_bh(&sh_chan->desc_lock); - - list_splice_init(&desc->tx_list, &sh_chan->ld_free); - list_add(&desc->node, &sh_chan->ld_free); - spin_unlock_bh(&sh_chan->desc_lock); - } + return NULL; } static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) @@ -252,11 +266,10 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) dma_async_tx_descriptor_init(&desc->async_tx, &sh_chan->common); desc->async_tx.tx_submit = sh_dmae_tx_submit; - desc->async_tx.flags = DMA_CTRL_ACK; - INIT_LIST_HEAD(&desc->tx_list); - sh_dmae_put_desc(sh_chan, desc); + desc->mark = DESC_IDLE; spin_lock_bh(&sh_chan->desc_lock); + list_add(&desc->node, &sh_chan->ld_free); sh_chan->descs_allocated++; } spin_unlock_bh(&sh_chan->desc_lock); @@ -273,7 +286,10 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) struct sh_desc *desc, *_desc; LIST_HEAD(list); - BUG_ON(!list_empty(&sh_chan->ld_queue)); + /* Prepared and not submitted descriptors can still be on the queue */ + if (!list_empty(&sh_chan->ld_queue)) + sh_dmae_chan_ld_cleanup(sh_chan, true); + spin_lock_bh(&sh_chan->desc_lock); list_splice_init(&sh_chan->ld_free, &list); @@ -292,6 +308,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( struct sh_dmae_chan *sh_chan; struct sh_desc *first = NULL, *prev = NULL, *new; size_t copy_size; + LIST_HEAD(tx_list); + int chunks = (len + SH_DMA_TCR_MAX) / (SH_DMA_TCR_MAX + 1); if (!chan) return NULL; @@ -301,108 +319,189 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( sh_chan = to_sh_chan(chan); + /* Have to lock the whole loop to protect against concurrent release */ + spin_lock_bh(&sh_chan->desc_lock); + + /* + * Chaining: + * first descriptor is what user is dealing with in all API calls, its + * cookie is at first set to -EBUSY, at tx-submit to a positive + * number + * if more than one chunk is needed further chunks have cookie = -EINVAL + * the last chunk, if not equal to the first, has cookie = -ENOSPC + * all chunks are linked onto the tx_list head with their .node heads + * only during this function, then they are immediately spliced + * back onto the free list in form of a chain + */ do { - /* Allocate the link descriptor from DMA pool */ + /* Allocate the link descriptor from the free list */ new = sh_dmae_get_desc(sh_chan); if (!new) { dev_err(sh_chan->dev, "No free memory for link descriptor\n"); - goto err_get_desc; + list_for_each_entry(new, &tx_list, node) + new->mark = DESC_IDLE; + list_splice(&tx_list, &sh_chan->ld_free); + spin_unlock_bh(&sh_chan->desc_lock); + return NULL; } - copy_size = min(len, (size_t)SH_DMA_TCR_MAX); + copy_size = min(len, (size_t)SH_DMA_TCR_MAX + 1); new->hw.sar = dma_src; new->hw.dar = dma_dest; new->hw.tcr = copy_size; - if (!first) + if (!first) { + /* First desc */ + new->async_tx.cookie = -EBUSY; first = new; + } else { + /* Other desc - invisible to the user */ + new->async_tx.cookie = -EINVAL; + } - new->mark = DESC_NCOMP; - async_tx_ack(&new->async_tx); + dev_dbg(sh_chan->dev, + "chaining %u of %u with %p, dst %x, cookie %d\n", + copy_size, len, &new->async_tx, dma_dest, + new->async_tx.cookie); + + new->mark = DESC_PREPARED; + new->async_tx.flags = flags; + new->chunks = chunks--; prev = new; len -= copy_size; dma_src += copy_size; dma_dest += copy_size; /* Insert the link descriptor to the LD ring */ - list_add_tail(&new->node, &first->tx_list); + list_add_tail(&new->node, &tx_list); } while (len); - new->async_tx.flags = flags; /* client is in control of this ack */ - new->async_tx.cookie = -EBUSY; /* Last desc */ + if (new != first) + new->async_tx.cookie = -ENOSPC; - return &first->async_tx; + /* Put them back on the free list, so, they don't get lost */ + list_splice_tail(&tx_list, &sh_chan->ld_free); -err_get_desc: - sh_dmae_put_desc(sh_chan, first); - return NULL; + spin_unlock_bh(&sh_chan->desc_lock); + return &first->async_tx; } -/* - * sh_chan_ld_cleanup - Clean up link descriptors - * - * This function clean up the ld_queue of DMA channel. - */ -static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan) +static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) { struct sh_desc *desc, *_desc; + /* Is the "exposed" head of a chain acked? */ + bool head_acked = false; + dma_cookie_t cookie = 0; + dma_async_tx_callback callback = NULL; + void *param = NULL; spin_lock_bh(&sh_chan->desc_lock); list_for_each_entry_safe(desc, _desc, &sh_chan->ld_queue, node) { - dma_async_tx_callback callback; - void *callback_param; - - /* non send data */ - if (desc->mark == DESC_NCOMP) + struct dma_async_tx_descriptor *tx = &desc->async_tx; + + BUG_ON(tx->cookie > 0 && tx->cookie != desc->cookie); + BUG_ON(desc->mark != DESC_SUBMITTED && + desc->mark != DESC_COMPLETED && + desc->mark != DESC_WAITING); + + /* + * queue is ordered, and we use this loop to (1) clean up all + * completed descriptors, and to (2) update descriptor flags of + * any chunks in a (partially) completed chain + */ + if (!all && desc->mark == DESC_SUBMITTED && + desc->cookie != cookie) break; - /* send data sesc */ - callback = desc->async_tx.callback; - callback_param = desc->async_tx.callback_param; + if (tx->cookie > 0) + cookie = tx->cookie; - /* Remove from ld_queue list */ - list_splice_init(&desc->tx_list, &sh_chan->ld_free); + if (desc->mark == DESC_COMPLETED && desc->chunks == 1) { + BUG_ON(sh_chan->completed_cookie != desc->cookie - 1); + sh_chan->completed_cookie = desc->cookie; + } - dev_dbg(sh_chan->dev, "link descriptor %p will be recycle.\n", - desc); + /* Call callback on the last chunk */ + if (desc->mark == DESC_COMPLETED && tx->callback) { + desc->mark = DESC_WAITING; + callback = tx->callback; + param = tx->callback_param; + dev_dbg(sh_chan->dev, "descriptor #%d@%p on %d callback\n", + tx->cookie, tx, sh_chan->id); + BUG_ON(desc->chunks != 1); + break; + } - list_move(&desc->node, &sh_chan->ld_free); - /* Run the link descriptor callback function */ - if (callback) { - spin_unlock_bh(&sh_chan->desc_lock); - dev_dbg(sh_chan->dev, "link descriptor %p callback\n", - desc); - callback(callback_param); - spin_lock_bh(&sh_chan->desc_lock); + if (tx->cookie > 0 || tx->cookie == -EBUSY) { + if (desc->mark == DESC_COMPLETED) { + BUG_ON(tx->cookie < 0); + desc->mark = DESC_WAITING; + } + head_acked = async_tx_test_ack(tx); + } else { + switch (desc->mark) { + case DESC_COMPLETED: + desc->mark = DESC_WAITING; + /* Fall through */ + case DESC_WAITING: + if (head_acked) + async_tx_ack(&desc->async_tx); + } + } + + dev_dbg(sh_chan->dev, "descriptor %p #%d completed.\n", + tx, tx->cookie); + + if (((desc->mark == DESC_COMPLETED || + desc->mark == DESC_WAITING) && + async_tx_test_ack(&desc->async_tx)) || all) { + /* Remove from ld_queue list */ + desc->mark = DESC_IDLE; + list_move(&desc->node, &sh_chan->ld_free); } } spin_unlock_bh(&sh_chan->desc_lock); + + if (callback) + callback(param); + + return callback; +} + +/* + * sh_chan_ld_cleanup - Clean up link descriptors + * + * This function cleans up the ld_queue of DMA channel. + */ +static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) +{ + while (__ld_cleanup(sh_chan, all)) + ; } static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan) { - struct list_head *ld_node; - struct sh_dmae_regs hw; + struct sh_desc *sd; + spin_lock_bh(&sh_chan->desc_lock); /* DMA work check */ - if (dmae_is_busy(sh_chan)) + if (dmae_is_busy(sh_chan)) { + spin_unlock_bh(&sh_chan->desc_lock); return; + } /* Find the first un-transfer desciptor */ - for (ld_node = sh_chan->ld_queue.next; - (ld_node != &sh_chan->ld_queue) - && (to_sh_desc(ld_node)->mark == DESC_COMP); - ld_node = ld_node->next) - cpu_relax(); - - if (ld_node != &sh_chan->ld_queue) { - /* Get the ld start address from ld_queue */ - hw = to_sh_desc(ld_node)->hw; - dmae_set_reg(sh_chan, hw); - dmae_start(sh_chan); - } + list_for_each_entry(sd, &sh_chan->ld_queue, node) + if (sd->mark == DESC_SUBMITTED) { + /* Get the ld start address from ld_queue */ + dmae_set_reg(sh_chan, &sd->hw); + dmae_start(sh_chan); + break; + } + + spin_unlock_bh(&sh_chan->desc_lock); } static void sh_dmae_memcpy_issue_pending(struct dma_chan *chan) @@ -420,12 +519,11 @@ static enum dma_status sh_dmae_is_complete(struct dma_chan *chan, dma_cookie_t last_used; dma_cookie_t last_complete; - sh_dmae_chan_ld_cleanup(sh_chan); + sh_dmae_chan_ld_cleanup(sh_chan, false); last_used = chan->cookie; last_complete = sh_chan->completed_cookie; - if (last_complete == -EBUSY) - last_complete = last_used; + BUG_ON(last_complete < 0); if (done) *done = last_complete; @@ -480,11 +578,13 @@ static irqreturn_t sh_dmae_err(int irq, void *data) err = sh_dmae_rst(0); if (err) return err; +#ifdef SH_DMAC_BASE1 if (shdev->pdata.mode & SHDMA_DMAOR1) { err = sh_dmae_rst(1); if (err) return err; } +#endif disable_irq(irq); return IRQ_HANDLED; } @@ -494,35 +594,25 @@ static irqreturn_t sh_dmae_err(int irq, void *data) static void dmae_do_tasklet(unsigned long data) { struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data; - struct sh_desc *desc, *_desc, *cur_desc = NULL; + struct sh_desc *desc; u32 sar_buf = sh_dmae_readl(sh_chan, SAR); - list_for_each_entry_safe(desc, _desc, - &sh_chan->ld_queue, node) { - if ((desc->hw.sar + desc->hw.tcr) == sar_buf) { - cur_desc = desc; + spin_lock(&sh_chan->desc_lock); + list_for_each_entry(desc, &sh_chan->ld_queue, node) { + if ((desc->hw.sar + desc->hw.tcr) == sar_buf && + desc->mark == DESC_SUBMITTED) { + dev_dbg(sh_chan->dev, "done #%d@%p dst %u\n", + desc->async_tx.cookie, &desc->async_tx, + desc->hw.dar); + desc->mark = DESC_COMPLETED; break; } } + spin_unlock(&sh_chan->desc_lock); - if (cur_desc) { - switch (cur_desc->async_tx.cookie) { - case 0: /* other desc data */ - break; - case -EBUSY: /* last desc */ - sh_chan->completed_cookie = - cur_desc->async_tx.cookie; - break; - default: /* first desc ( 0 < )*/ - sh_chan->completed_cookie = - cur_desc->async_tx.cookie - 1; - break; - } - cur_desc->mark = DESC_COMP; - } /* Next desc */ sh_chan_xfer_ld_queue(sh_chan); - sh_dmae_chan_ld_cleanup(sh_chan); + sh_dmae_chan_ld_cleanup(sh_chan, false); } static unsigned int get_dmae_irq(unsigned int id) diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 60b81e529b4..108f1cffb6f 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -13,9 +13,9 @@ #ifndef __DMA_SHDMA_H #define __DMA_SHDMA_H -#include -#include #include +#include +#include #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ @@ -26,13 +26,16 @@ struct sh_dmae_regs { }; struct sh_desc { - struct list_head tx_list; struct sh_dmae_regs hw; struct list_head node; struct dma_async_tx_descriptor async_tx; + dma_cookie_t cookie; + int chunks; int mark; }; +struct device; + struct sh_dmae_chan { dma_cookie_t completed_cookie; /* The maximum cookie completed */ spinlock_t desc_lock; /* Descriptor operation lock */ -- cgit v1.2.3 From c566ec49159b806db95a90fd8f37448376cd0ad2 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Thu, 17 Dec 2009 16:12:56 +0800 Subject: drm/i915: Reload hangcheck timer too for Ironlake Make sure hangcheck timer won't beat us unexpectedly on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_irq.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1733eea8784..7cd8110051b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -313,6 +313,8 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) dev_priv->mm.irq_gem_seqno = seqno; trace_i915_gem_request_complete(dev, seqno); DRM_WAKEUP(&dev_priv->irq_queue); + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); } if (de_iir & DE_GSE) -- cgit v1.2.3 From cd78809f6191485a90ea6c92c2b58900ab5c156f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 17 Dec 2009 13:52:39 -0700 Subject: ioat3: fix p-disabled q-continuation When continuing a pq calculation the driver needs 3 extra sources. The driver can perform a 3 source calculation with a single descriptor, but needs an extended descriptor to process up to 8 sources in one operation. However, in the p-disabled case only one extra source is needed. When continuing a p-disabled operation there are occasions (i.e. 0 < src_cnt % 8 < 3) where the tail operation does not need an extended descriptor. Properly account for this fact otherwise invalid 'dmacount' values will be written to hardware usually causing the channel to halt with 'invalid descriptor' errors. Cc: Signed-off-by: Dan Williams --- drivers/dma/ioat/dma_v3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index 42f6f10fb0c..e58ecb29513 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -650,9 +650,11 @@ __ioat3_prep_pq_lock(struct dma_chan *c, enum sum_check_flags *result, num_descs = ioat2_xferlen_to_descs(ioat, len); /* we need 2x the number of descriptors to cover greater than 3 - * sources + * sources (we need 1 extra source in the q-only continuation + * case and 3 extra sources in the p+q continuation case. */ - if (src_cnt > 3 || flags & DMA_PREP_CONTINUE) { + if (src_cnt + dmaf_p_disabled_continue(flags) > 3 || + (dmaf_continue(flags) && !dmaf_p_disabled_continue(flags))) { with_ext = 1; num_descs *= 2; } else -- cgit v1.2.3 From d54e7929d8073b0fff8af16f8ff6ebbba6fc4154 Mon Sep 17 00:00:00 2001 From: Thomas Champagne Date: Fri, 18 Dec 2009 03:41:41 +0300 Subject: pmu_battery: Fix battery full reporting Prior to this patch, pmu_battery was unable to report battery full status. This patch fixes the issue by adding a proper handling code into pmu_bat_get_property(): if we're on AC and the battery isn't charging, then the battery is considered full. Signed-off-by: Thomas Champagne Acked-By: David Woodhouse Signed-off-by: Anton Vorontsov --- drivers/power/pmu_battery.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/power/pmu_battery.c b/drivers/power/pmu_battery.c index 9346a862f1f..9c87ad56480 100644 --- a/drivers/power/pmu_battery.c +++ b/drivers/power/pmu_battery.c @@ -89,6 +89,8 @@ static int pmu_bat_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_STATUS: if (pbi->flags & PMU_BATT_CHARGING) val->intval = POWER_SUPPLY_STATUS_CHARGING; + else if (pmu_power_flags & PMU_PWR_AC_PRESENT) + val->intval = POWER_SUPPLY_STATUS_FULL; else val->intval = POWER_SUPPLY_STATUS_DISCHARGING; break; -- cgit v1.2.3 From 4a63b030d75a063b910b2bab014d84837cb33eb7 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 18 Dec 2009 12:38:11 +0100 Subject: drbd: fix test of unsigned in _drbd_fault_random() rsp->count is unsigned so the test does not work. Signed-off-by: Roel Kluin Cc: Lars Ellenberg Cc: Philipp Reisner Signed-off-by: Jens Axboe --- drivers/block/drbd/drbd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 157d1e4343c..c2594c137e6 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3623,7 +3623,7 @@ _drbd_fault_random(struct fault_random_state *rsp) { long refresh; - if (--rsp->count < 0) { + if (!rsp->count--) { get_random_bytes(&refresh, sizeof(refresh)); rsp->state += refresh; rsp->count = FAULT_RANDOM_REFRESH; -- cgit v1.2.3 From a6d52d70677e99bdb89b6921c265d0a58c22e597 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 19 Dec 2009 15:36:02 -0700 Subject: ioat2,3: put channel hardware in known state at init Put the ioat2 and ioat3 state machines in the halted state with all errors cleared. The ioat1 init path is not disturbed for stability, there are no reported ioat1 initiaization issues. Cc: Reported-by: Roland Dreier Tested-by: Roland Dreier Acked-by: Simon Horman Signed-off-by: Dan Williams --- drivers/dma/ioat/dma.c | 2 +- drivers/dma/ioat/dma.h | 18 ++++++++++++ drivers/dma/ioat/dma_v2.c | 69 +++++++++++++++++++++++++++++++++----------- drivers/dma/ioat/dma_v2.h | 2 ++ drivers/dma/ioat/dma_v3.c | 54 +++++++++++++++++++++++++--------- drivers/dma/ioat/registers.h | 1 + 6 files changed, 114 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index c524d36d3c2..dcc4ab78b32 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -1032,7 +1032,7 @@ int __devinit ioat_probe(struct ioatdma_device *device) dma->dev = &pdev->dev; if (!dma->chancnt) { - dev_err(dev, "zero channels detected\n"); + dev_err(dev, "channel enumeration error\n"); goto err_setup_interrupts; } diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 45edde99648..bbc3e78ef33 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -60,6 +60,7 @@ * @dca: direct cache access context * @intr_quirk: interrupt setup quirk (for ioat_v1 devices) * @enumerate_channels: hw version specific channel enumeration + * @reset_hw: hw version specific channel (re)initialization * @cleanup_tasklet: select between the v2 and v3 cleanup routines * @timer_fn: select between the v2 and v3 timer watchdog routines * @self_test: hardware version specific self test for each supported op type @@ -78,6 +79,7 @@ struct ioatdma_device { struct dca_provider *dca; void (*intr_quirk)(struct ioatdma_device *device); int (*enumerate_channels)(struct ioatdma_device *device); + int (*reset_hw)(struct ioat_chan_common *chan); void (*cleanup_tasklet)(unsigned long data); void (*timer_fn)(unsigned long data); int (*self_test)(struct ioatdma_device *device); @@ -264,6 +266,22 @@ static inline void ioat_suspend(struct ioat_chan_common *chan) writeb(IOAT_CHANCMD_SUSPEND, chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); } +static inline void ioat_reset(struct ioat_chan_common *chan) +{ + u8 ver = chan->device->version; + + writeb(IOAT_CHANCMD_RESET, chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); +} + +static inline bool ioat_reset_pending(struct ioat_chan_common *chan) +{ + u8 ver = chan->device->version; + u8 cmd; + + cmd = readb(chan->reg_base + IOAT_CHANCMD_OFFSET(ver)); + return (cmd & IOAT_CHANCMD_RESET) == IOAT_CHANCMD_RESET; +} + static inline void ioat_set_chainaddr(struct ioat_dma_chan *ioat, u64 addr) { struct ioat_chan_common *chan = &ioat->base; diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c index 8f1f7f05dea..5f7a500e18d 100644 --- a/drivers/dma/ioat/dma_v2.c +++ b/drivers/dma/ioat/dma_v2.c @@ -239,20 +239,50 @@ void __ioat2_restart_chan(struct ioat2_dma_chan *ioat) __ioat2_start_null_desc(ioat); } -static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) +int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo) { - struct ioat_chan_common *chan = &ioat->base; - unsigned long phys_complete; + unsigned long end = jiffies + tmo; + int err = 0; u32 status; status = ioat_chansts(chan); if (is_ioat_active(status) || is_ioat_idle(status)) ioat_suspend(chan); while (is_ioat_active(status) || is_ioat_idle(status)) { + if (end && time_after(jiffies, end)) { + err = -ETIMEDOUT; + break; + } status = ioat_chansts(chan); cpu_relax(); } + return err; +} + +int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo) +{ + unsigned long end = jiffies + tmo; + int err = 0; + + ioat_reset(chan); + while (ioat_reset_pending(chan)) { + if (end && time_after(jiffies, end)) { + err = -ETIMEDOUT; + break; + } + cpu_relax(); + } + + return err; +} + +static void ioat2_restart_channel(struct ioat2_dma_chan *ioat) +{ + struct ioat_chan_common *chan = &ioat->base; + unsigned long phys_complete; + + ioat2_quiesce(chan, 0); if (ioat_cleanup_preamble(chan, &phys_complete)) __cleanup(ioat, phys_complete); @@ -318,6 +348,19 @@ void ioat2_timer_event(unsigned long data) spin_unlock_bh(&chan->cleanup_lock); } +static int ioat2_reset_hw(struct ioat_chan_common *chan) +{ + /* throw away whatever the channel was doing and get it initialized */ + u32 chanerr; + + ioat2_quiesce(chan, msecs_to_jiffies(100)); + + chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); + + return ioat2_reset_sync(chan, msecs_to_jiffies(200)); +} + /** * ioat2_enumerate_channels - find and initialize the device's channels * @device: the device to be enumerated @@ -360,6 +403,10 @@ int ioat2_enumerate_channels(struct ioatdma_device *device) (unsigned long) ioat); ioat->xfercap_log = xfercap_log; spin_lock_init(&ioat->ring_lock); + if (device->reset_hw(&ioat->base)) { + i = 0; + break; + } } dma->chancnt = i; return i; @@ -467,7 +514,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) struct ioat2_dma_chan *ioat = to_ioat2_chan(c); struct ioat_chan_common *chan = &ioat->base; struct ioat_ring_ent **ring; - u32 chanerr; int order; /* have we already been set up? */ @@ -477,12 +523,6 @@ int ioat2_alloc_chan_resources(struct dma_chan *c) /* Setup register to interrupt and write completion status on error */ writew(IOAT_CHANCTRL_RUN, chan->reg_base + IOAT_CHANCTRL_OFFSET); - chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); - if (chanerr) { - dev_err(to_dev(chan), "CHANERR = %x, clearing\n", chanerr); - writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); - } - /* allocate a completion writeback area */ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ chan->completion = pci_pool_alloc(chan->device->completion_pool, @@ -746,13 +786,7 @@ void ioat2_free_chan_resources(struct dma_chan *c) tasklet_disable(&chan->cleanup_task); del_timer_sync(&chan->timer); device->cleanup_tasklet((unsigned long) ioat); - - /* Delay 100ms after reset to allow internal DMA logic to quiesce - * before removing DMA descriptor resources. - */ - writeb(IOAT_CHANCMD_RESET, - chan->reg_base + IOAT_CHANCMD_OFFSET(chan->device->version)); - mdelay(100); + device->reset_hw(chan); spin_lock_bh(&ioat->ring_lock); descs = ioat2_ring_space(ioat); @@ -839,6 +873,7 @@ int __devinit ioat2_dma_probe(struct ioatdma_device *device, int dca) int err; device->enumerate_channels = ioat2_enumerate_channels; + device->reset_hw = ioat2_reset_hw; device->cleanup_tasklet = ioat2_cleanup_tasklet; device->timer_fn = ioat2_timer_event; device->self_test = ioat_dma_self_test; diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h index 1d849ef74d5..3afad8da43c 100644 --- a/drivers/dma/ioat/dma_v2.h +++ b/drivers/dma/ioat/dma_v2.h @@ -185,6 +185,8 @@ bool reshape_ring(struct ioat2_dma_chan *ioat, int order); void __ioat2_issue_pending(struct ioat2_dma_chan *ioat); void ioat2_cleanup_tasklet(unsigned long data); void ioat2_timer_event(unsigned long data); +int ioat2_quiesce(struct ioat_chan_common *chan, unsigned long tmo); +int ioat2_reset_sync(struct ioat_chan_common *chan, unsigned long tmo); extern struct kobj_type ioat2_ktype; extern struct kmem_cache *ioat2_cache; #endif /* IOATDMA_V2_H */ diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e58ecb29513..9908c9e94b2 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -1130,6 +1130,45 @@ static int __devinit ioat3_dma_self_test(struct ioatdma_device *device) return 0; } +static int ioat3_reset_hw(struct ioat_chan_common *chan) +{ + /* throw away whatever the channel was doing and get it + * initialized, with ioat3 specific workarounds + */ + struct ioatdma_device *device = chan->device; + struct pci_dev *pdev = device->pdev; + u32 chanerr; + u16 dev_id; + int err; + + ioat2_quiesce(chan, msecs_to_jiffies(100)); + + chanerr = readl(chan->reg_base + IOAT_CHANERR_OFFSET); + writel(chanerr, chan->reg_base + IOAT_CHANERR_OFFSET); + + /* -= IOAT ver.3 workarounds =- */ + /* Write CHANERRMSK_INT with 3E07h to mask out the errors + * that can cause stability issues for IOAT ver.3, and clear any + * pending errors + */ + pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); + err = pci_read_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, &chanerr); + if (err) { + dev_err(&pdev->dev, "channel error register unreachable\n"); + return err; + } + pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr); + + /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit + * (workaround for spurious config parity error after restart) + */ + pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id); + if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) + pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10); + + return ioat2_reset_sync(chan, msecs_to_jiffies(200)); +} + int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) { struct pci_dev *pdev = device->pdev; @@ -1139,10 +1178,10 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) struct ioat_chan_common *chan; bool is_raid_device = false; int err; - u16 dev_id; u32 cap; device->enumerate_channels = ioat2_enumerate_channels; + device->reset_hw = ioat3_reset_hw; device->self_test = ioat3_dma_self_test; dma = &device->common; dma->device_prep_dma_memcpy = ioat2_dma_prep_memcpy_lock; @@ -1218,19 +1257,6 @@ int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca) dma->device_prep_dma_xor_val = NULL; #endif - /* -= IOAT ver.3 workarounds =- */ - /* Write CHANERRMSK_INT with 3E07h to mask out the errors - * that can cause stability issues for IOAT ver.3 - */ - pci_write_config_dword(pdev, IOAT_PCI_CHANERRMASK_INT_OFFSET, 0x3e07); - - /* Clear DMAUNCERRSTS Cfg-Reg Parity Error status bit - * (workaround for spurious config parity error after restart) - */ - pci_read_config_word(pdev, IOAT_PCI_DEVICE_ID_OFFSET, &dev_id); - if (dev_id == PCI_DEVICE_ID_INTEL_IOAT_TBG0) - pci_write_config_dword(pdev, IOAT_PCI_DMAUNCERRSTS_OFFSET, 0x10); - err = ioat_probe(device); if (err) return err; diff --git a/drivers/dma/ioat/registers.h b/drivers/dma/ioat/registers.h index f015ec19670..e8ae63baf58 100644 --- a/drivers/dma/ioat/registers.h +++ b/drivers/dma/ioat/registers.h @@ -27,6 +27,7 @@ #define IOAT_PCI_DEVICE_ID_OFFSET 0x02 #define IOAT_PCI_DMAUNCERRSTS_OFFSET 0x148 +#define IOAT_PCI_CHANERR_INT_OFFSET 0x180 #define IOAT_PCI_CHANERRMASK_INT_OFFSET 0x184 /* MMIO Device Registers */ -- cgit v1.2.3 From cdd90fb575807622e69245d5c3048281f47c77b3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Dec 2009 23:36:00 +0000 Subject: ARM: add missing include to nwflash.c nwflash needs jiffie definitions. Signed-off-by: Russell King --- drivers/char/nwflash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 8c7df5ba088..f80810901db 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 7d4e9d0962cd0f6a30b01e256756dd10606dab30 Mon Sep 17 00:00:00 2001 From: Emese Revfy Date: Mon, 14 Dec 2009 00:59:30 +0100 Subject: drbd: Constify struct file_operations Signed-off-by: Emese Revfy Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_int.h | 2 +- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_proc.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 2312d782fe9..c9755876343 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1490,7 +1490,7 @@ void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo); /* drbd_proc.c */ extern struct proc_dir_entry *drbd_proc; -extern struct file_operations drbd_proc_fops; +extern const struct file_operations drbd_proc_fops; extern const char *drbd_conn_str(enum drbd_conns s); extern const char *drbd_role_str(enum drbd_role s); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 157d1e4343c..af30ca97493 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -151,7 +151,7 @@ wait_queue_head_t drbd_pp_wait; DEFINE_RATELIMIT_STATE(drbd_ratelimit_state, 5 * HZ, 5); -static struct block_device_operations drbd_ops = { +static const struct block_device_operations drbd_ops = { .owner = THIS_MODULE, .open = drbd_open, .release = drbd_release, diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index bdd0b4943b1..df8ad9660d8 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -38,7 +38,7 @@ static int drbd_proc_open(struct inode *inode, struct file *file); struct proc_dir_entry *drbd_proc; -struct file_operations drbd_proc_fops = { +const struct file_operations drbd_proc_fops = { .owner = THIS_MODULE, .open = drbd_proc_open, .read = seq_read, -- cgit v1.2.3 From 49829ea74f790d3be2e803a617e714f5b9a5ed50 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 15 Dec 2009 22:55:44 +0100 Subject: drbd: Fix test of unsigned in _drbd_fault_random() rsp->count is unsigned so the test does not work. Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index af30ca97493..ecc1612df67 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -3623,7 +3623,7 @@ _drbd_fault_random(struct fault_random_state *rsp) { long refresh; - if (--rsp->count < 0) { + if (!rsp->count--) { get_random_bytes(&refresh, sizeof(refresh)); rsp->state += refresh; rsp->count = FAULT_RANDOM_REFRESH; -- cgit v1.2.3 From 7b886f4f7a051dc88165684cbcddd98e22bd0203 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Wed, 9 Dec 2009 21:09:12 +0800 Subject: drbd: remove duplicated #include Remove duplicated #include('s) in drivers/block/drbd/drbd_worker.c Signed-off-by: Huang Weiyi Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_worker.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index ed8796f1112..3e8b6bc0ec2 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 820cd61a28503598f4262c544082ccb33678b9fc Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 13 Dec 2009 22:05:03 +0800 Subject: drbd: remove unused #include Remove unused #include ('s) in drivers/block/drbd/drbd_main.c drivers/block/drbd/drbd_receiver.c drivers/block/drbd/drbd_worker.c Signed-off-by: Huang Weiyi Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_main.c | 1 - drivers/block/drbd/drbd_receiver.c | 1 - drivers/block/drbd/drbd_worker.c | 1 - 3 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index ecc1612df67..9348f33f624 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -27,7 +27,6 @@ */ #include -#include #include #include #include diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index c548f24f54a..259c1351b15 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 3e8b6bc0ec2..b453c2bca3b 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -24,7 +24,6 @@ */ #include -#include #include #include #include -- cgit v1.2.3 From 81074e90f5c150ca70ab8dfcc77860cbe76f364d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Dec 2009 16:13:15 +0800 Subject: ACPI: disable _OSI(Windows 2009) on Asus K50IJ Fix a win7 compability issue on Asus K50IJ. Here is the _BCM method of this laptop: Method (_BCM, 1, NotSerialized) { If (LGreaterEqual (OSFG, OSVT)) { If (LNotEqual (OSFG, OSW7)) { Store (One, BCMD) Store (GCBL (Arg0), Local0) Subtract (0x0F, Local0, LBTN) ^^^SBRG.EC0.STBR () ... } Else { DBGR (0x0B, Zero, Zero, Arg0) Store (Arg0, LBTN) ^^^SBRG.EC0.STBR () ... } } } LBTN is used to store the index of the brightness level in the _BCL. GCBL is a method that convert the percentage value to the index value. If _OSI(Windows 2009) is not disabled, LBTN is stored a percentage value which is surely beyond the end of _BCL package. http://bugzilla.kernel.org/show_bug.cgi?id=14753 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/blacklist.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 23e5a0519af..2815df66f6f 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -185,6 +185,12 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) acpi_osi_setup("!Windows 2006"); return 0; } +static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2009"); + return 0; +} static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { { @@ -211,6 +217,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), }, }, + { + .callback = dmi_disable_osi_win7, + .ident = "ASUS K50IJ", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3 From 55b313f249e11b815fd0be51869f166aaf368f44 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 22 Dec 2009 02:42:52 -0500 Subject: ACPI: EC: Fix MSI DMI detection MSI strings should be ORed, not ANDed. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14446 cc: stable@kernel.org Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index baef28c1e63..7511029a1e0 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -916,6 +916,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) /* MSI EC needs special treatment, enable it */ static int ec_flag_msi(const struct dmi_system_id *id) { + printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); EC_FLAGS_MSI = 1; EC_FLAGS_VALIDATE_ECDT = 1; return 0; @@ -928,8 +929,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL}, { ec_flag_msi, "MSI hardware", { - DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"), - DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL}, + DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, -- cgit v1.2.3 From df9dc83d193959f990c981787279e8541fe9df8c Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 21 Dec 2009 16:27:49 -0800 Subject: drivers/block/DAC960.c: use DAC960_V2_Controller DAC960_LP_Controller and DAC960_V2_Controller have the same value, but elsewhere it is DAC960_V1_Controller or DAC960_V2_Controller that is used in the FirmwareType field. Signed-off-by: Julia Lawall Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/DAC960.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index eb4fa194394..ce1fa923c41 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -7101,7 +7101,7 @@ static struct DAC960_privdata DAC960_BA_privdata = { static struct DAC960_privdata DAC960_LP_privdata = { .HardwareType = DAC960_LP_Controller, - .FirmwareType = DAC960_LP_Controller, + .FirmwareType = DAC960_V2_Controller, .InterruptHandler = DAC960_LP_InterruptHandler, .MemoryWindowSize = DAC960_LP_RegisterWindowSize, }; -- cgit v1.2.3 From e019ef0c4f11a0acb79b89fb1e09c72197b42bbe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 21 Dec 2009 16:27:49 -0800 Subject: drivers/block/mg_disk.c: use resource_size() Use resource_size() for ioremap. The ioremap appears to be passing the incorrect size for the platform resource. Unfortunately, I can't locate a user in mainline to verify this. Using resource_size should be the correct fix. Signed-off-by: H Hartley Sweeten Acked-by: unsik Kim Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/mg_disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index e0339aaa181..02b2583df7f 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c @@ -860,7 +860,7 @@ static int mg_probe(struct platform_device *plat_dev) err = -EINVAL; goto probe_err_2; } - host->dev_base = ioremap(rsc->start , rsc->end + 1); + host->dev_base = ioremap(rsc->start, resource_size(rsc)); if (!host->dev_base) { printk(KERN_ERR "%s:%d ioremap fail\n", __func__, __LINE__); -- cgit v1.2.3 From 6ec1480d8539c8e2e6ba7fbbeffe5adc640bfe98 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 21 Dec 2009 16:27:50 -0800 Subject: aoe: switch to the new bio_flush_dcache_pages() interface Cc: "Ed L. Cashin" Cc: David Woodhouse Cc: Ilya Loginov Cc: Ingo Molnar Cc: Peter Horton Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/aoe/aoecmd.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 13bb69d2abb..64a223b0cc2 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -735,21 +735,6 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector part_stat_unlock(); } -/* - * Ensure we don't create aliases in VI caches - */ -static inline void -killalias(struct bio *bio) -{ - struct bio_vec *bv; - int i; - - if (bio_data_dir(bio) == READ) - __bio_for_each_segment(bv, bio, i, 0) { - flush_dcache_page(bv->bv_page); - } -} - void aoecmd_ata_rsp(struct sk_buff *skb) { @@ -871,7 +856,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (buf->flags & BUFFL_FAIL) bio_endio(buf->bio, -EIO); else { - killalias(buf->bio); + bio_flush_dcache_pages(buf->bio); bio_endio(buf->bio, 0); } mempool_free(buf, d->bufpool); -- cgit v1.2.3 From 78f1699659963fff97975df44db6d5dbe7218e55 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:09 -0700 Subject: ACPI: processor: call _PDC early We discovered that at least one machine (HP Envy), methods in the DSDT attempt to call external methods defined in a dynamically loaded SSDT. Unfortunately, the DSDT methods we are trying to call are part of the EC initialization, which happens very early, and the the dynamic SSDT is only loaded when a processor _PDC method runs much later. This results in namespace lookup errors for the (as of yet) undefined methods. Since Windows doesn't have any issues with this machine, we take it as a hint that they must be evaluating _PDC much earlier than we are. Thus, the proper thing for Linux to do should be to match the Windows implementation more closely. Provide a mechanism to call _PDC before we enable the EC. Doing so loads the dynamic tables, and allows the EC to be enabled correctly. The ACPI processor driver will still evaluate _PDC in its .add() method to cover the hotplug case. Resolves: http://bugzilla.kernel.org/show_bug.cgi?id=14824 Cc: ming.m.lin@intel.com Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/Makefile | 1 + drivers/acpi/bus.c | 2 + drivers/acpi/internal.h | 1 + drivers/acpi/processor_core.c | 69 --------------------------- drivers/acpi/processor_pdc.c | 108 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 69 deletions(-) create mode 100644 drivers/acpi/processor_pdc.c (limited to 'drivers') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c7b10b4298e..66cc3f36a95 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -32,6 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o # acpi-y += bus.o glue.o acpi-y += scan.o +acpi-y += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f12..0bdf24a6fd0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -888,6 +888,8 @@ static int __init acpi_bus_init(void) goto error1; } + acpi_early_processor_set_pdc(); + /* * Maybe EC region is required at bus_scan/acpi_get_devices. So it * is necessary to enable it as early as possible. diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 074cf8682d5..cb28e0502ac 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -43,6 +43,7 @@ int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; int acpi_wakeup_device_init(void); +void acpi_early_processor_set_pdc(void); /* -------------------------------------------------------------------------- Embedded Controller diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 41731236f9a..a19a4ff962e 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -124,29 +124,6 @@ static const struct file_operations acpi_processor_info_fops = { DEFINE_PER_CPU(struct acpi_processor *, processors); struct acpi_processor_errata errata __read_mostly; -static int set_no_mwait(const struct dmi_system_id *id) -{ - printk(KERN_NOTICE PREFIX "%s detected - " - "disabling mwait for CPU C-states\n", id->ident); - idle_nomwait = 1; - return 0; -} - -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"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; /* -------------------------------------------------------------------------- Errata Handling @@ -276,45 +253,6 @@ static int acpi_processor_errata(struct acpi_processor *pr) return result; } -/* -------------------------------------------------------------------------- - Common ACPI processor functions - -------------------------------------------------------------------------- */ - -/* - * _PDC is required for a BIOS-OS handshake for most of the newer - * ACPI processor features. - */ -static int acpi_processor_set_pdc(struct acpi_processor *pr) -{ - struct acpi_object_list *pdc_in = pr->pdc; - acpi_status status = AE_OK; - - - if (!pdc_in) - return status; - if (idle_nomwait) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); - - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Could not evaluate _PDC, using legacy perf. control...\n")); - - return status; -} - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -825,9 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); @@ -1145,11 +1081,6 @@ static int __init acpi_processor_init(void) if (!acpi_processor_dir) return -ENOMEM; #endif - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); result = cpuidle_register_driver(&acpi_idle_driver); if (result < 0) goto out_proc; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c new file mode 100644 index 00000000000..b416c32dda0 --- /dev/null +++ b/drivers/acpi/processor_pdc.c @@ -0,0 +1,108 @@ +#include + +#include +#include + +#include "internal.h" + +#define PREFIX "ACPI: " +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME("processor_pdc"); + +static int set_no_mwait(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE PREFIX "%s detected - " + "disabling mwait for CPU C-states\n", id->ident); + idle_nomwait = 1; + return 0; +} + +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"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, + {}, +}; + +/* + * _PDC is required for a BIOS-OS handshake for most of the newer + * ACPI processor features. + */ +static int acpi_processor_eval_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *pdc_in = pr->pdc; + acpi_status status = AE_OK; + + if (!pdc_in) + return status; + if (idle_nomwait) { + /* + * If mwait is disabled for CPU C-states, the C2C3_FFH access + * mode will be disabled in the parameter of _PDC object. + * Of course C1_FFH access mode will also be disabled. + */ + union acpi_object *obj; + u32 *buffer = NULL; + + obj = pdc_in->pointer; + buffer = (u32 *)(obj->buffer.pointer); + buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); + + } + status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Could not evaluate _PDC, using legacy perf. control.\n")); + + return status; +} + +void acpi_processor_set_pdc(struct acpi_processor *pr) +{ + arch_acpi_processor_init_pdc(pr); + acpi_processor_eval_pdc(pr); + arch_acpi_processor_cleanup_pdc(pr); +} +EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); + +static acpi_status +early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpi_processor pr; + + pr.handle = handle; + + /* x86 implementation looks at pr.id to determine some + * CPU capabilites. We can just hard code to 0 since we're + * assuming the CPUs in the system are homogenous and all + * have the same capabilities. + */ + pr.id = 0; + + acpi_processor_set_pdc(&pr); + + return AE_OK; +} + +void acpi_early_processor_set_pdc(void) +{ + /* + * Check whether the system is DMI table. If yes, OSPM + * should not use mwait for CPU-states. + */ + dmi_check_system(processor_idle_dmi_table); + + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + early_init_pdc, NULL, NULL, NULL); +} -- cgit v1.2.3 From 1d9cb470a755409ce97c3376174b1e234bd20371 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:14 -0700 Subject: ACPI: processor: introduce arch_has_acpi_pdc arch dependent helper function that tells us if we should attempt to evaluate _PDC on this machine or not. The x86 implementation assumes that the CPUs in the machine must be homogeneous, and that you cannot mix CPUs of different vendors. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index b416c32dda0..931e735e9e3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -69,6 +69,9 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + if (arch_has_acpi_pdc() == false) + return; + arch_acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); -- cgit v1.2.3 From 407cd87c54e76c266245e8faef8dd4a84b7254fe Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:19 -0700 Subject: ACPI: processor: unify arch_acpi_processor_init_pdc The x86 and ia64 implementations of arch_acpi_processor_init_pdc() are almost exactly the same. The only difference is in what bits they set in obj_list buffer. Combine the boilerplate memory management code, and leave the arch-specific bit twiddling in separate implementations. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 931e735e9e3..87946b6da76 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,49 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_processor_init_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + pr->pdc = NULL; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return; + } + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return; + } + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + /* Now let the arch do the bit-twiddling to buf[] */ + arch_acpi_processor_init_pdc(pr); + + return; +} + /* * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. @@ -72,7 +115,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (arch_has_acpi_pdc() == false) return; - arch_acpi_processor_init_pdc(pr); + acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3 From 08ea48a326d8030ef5b7fb02292faf5a53c95e0a Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:24 -0700 Subject: ACPI: processor: factor out common _PDC settings Both x86 and ia64 initialize _PDC with mostly common bit settings. Factor out the common settings and leave the arch-specific ones alone. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 87946b6da76..ccda7c95d07 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,15 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_set_pdc_bits(u32 *buf) +{ + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + + /* Enable coordination with firmware's _TSD info */ + buf[2] = ACPI_PDC_SMP_T_SWCOORD; +} + static void acpi_processor_init_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -63,6 +72,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) return; } + acpi_set_pdc_bits(buf); + obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; obj->buffer.pointer = (u8 *) buf; -- cgit v1.2.3 From 6c5807d7bc7d051fce00863ffb98d36325501eb2 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:29 -0700 Subject: ACPI: processor: finish unifying arch_acpi_processor_init_pdc() The only thing arch-specific about calling _PDC is what bits get set in the input obj_list buffer. There's no need for several levels of indirection to twiddle those bits. Additionally, since we're just messing around with a buffer, we can simplify the interface; no need to pass around the entire struct acpi_processor * just to get at the buffer. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index ccda7c95d07..48df08ebcec 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -40,6 +40,9 @@ static void acpi_set_pdc_bits(u32 *buf) /* Enable coordination with firmware's _TSD info */ buf[2] = ACPI_PDC_SMP_T_SWCOORD; + + /* Twiddle arch-specific bits needed for _PDC */ + arch_acpi_set_pdc_bits(buf); } static void acpi_processor_init_pdc(struct acpi_processor *pr) @@ -81,9 +84,6 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj_list->pointer = obj; pr->pdc = obj_list; - /* Now let the arch do the bit-twiddling to buf[] */ - arch_acpi_processor_init_pdc(pr); - return; } -- cgit v1.2.3 From 47817254b8637b56730aec26eed2c337d3938bb5 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:34 -0700 Subject: ACPI: processor: unify arch_acpi_processor_cleanup_pdc The x86 and ia64 implementations of the function in $subject are exactly the same. Also, since the arch-specific implementations of setting _PDC have been completely hollowed out, remove the empty shells. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 48df08ebcec..e786e2ce188 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -1,3 +1,12 @@ +/* + * Copyright (C) 2005 Intel Corporation + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * + * Alex Chiang + * - Unified x86/ia64 implementations + * Venkatesh Pallipadi + * - Added _PDC for platforms with Intel CPUs + */ #include #include @@ -121,6 +130,16 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) return status; } +static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) +{ + if (pr->pdc) { + kfree(pr->pdc->pointer->buffer.pointer); + kfree(pr->pdc->pointer); + kfree(pr->pdc); + pr->pdc = NULL; + } +} + void acpi_processor_set_pdc(struct acpi_processor *pr) { if (arch_has_acpi_pdc() == false) @@ -128,7 +147,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); + acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From 3b407aef573b82139c3bc4dcaad2731fad56c054 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:39 -0700 Subject: ACPI: processor: introduce acpi_processor_alloc_pdc() acpi_processor_init_pdc() isn't really doing anything interesting with the struct acpi_processor * parameter. Its real job is to allocate the buffer for the _PDC bits. So rename the function to acpi_processor_alloc_pdc(), and just return the struct acpi_object_list * it's supposed to allocate. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index e786e2ce188..23d2828157e 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -54,26 +54,24 @@ static void acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static void acpi_processor_init_pdc(struct acpi_processor *pr) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; u32 *buf; - pr->pdc = NULL; - /* allocate and initialize pdc. It will be used later. */ obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); if (!obj_list) { printk(KERN_ERR "Memory allocation error\n"); - return; + return NULL; } obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!obj) { printk(KERN_ERR "Memory allocation error\n"); kfree(obj_list); - return; + return NULL; } buf = kmalloc(12, GFP_KERNEL); @@ -81,7 +79,7 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) printk(KERN_ERR "Memory allocation error\n"); kfree(obj); kfree(obj_list); - return; + return NULL; } acpi_set_pdc_bits(buf); @@ -91,9 +89,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj->buffer.pointer = (u8 *) buf; obj_list->count = 1; obj_list->pointer = obj; - pr->pdc = obj_list; - return; + return obj_list; } /* @@ -142,10 +139,17 @@ static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + struct acpi_object_list *obj_list; + if (arch_has_acpi_pdc() == false) return; - acpi_processor_init_pdc(pr); + obj_list = acpi_processor_alloc_pdc(); + if (!obj_list) + return; + + pr->pdc = obj_list; + acpi_processor_eval_pdc(pr); acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3 From fa118564ed66f785f957d8230745b62e9244700d Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:45 -0700 Subject: ACPI: processor: change acpi_processor_eval_pdc interface acpi_processor_eval_pdc() really only needs a handle and an acpi_object_list * to do its work. No need to pass in a struct acpi_processor *, so let's be more specific about what we want. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 23d2828157e..974de4eb298 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -97,13 +97,11 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int acpi_processor_eval_pdc(struct acpi_processor *pr) +static int +acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { - struct acpi_object_list *pdc_in = pr->pdc; acpi_status status = AE_OK; - if (!pdc_in) - return status; if (idle_nomwait) { /* * If mwait is disabled for CPU C-states, the C2C3_FFH access @@ -118,7 +116,7 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -148,9 +146,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - pr->pdc = obj_list; - - acpi_processor_eval_pdc(pr); + acpi_processor_eval_pdc(pr->handle, obj_list); acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From b9c2db783456bcbce31e2482214cd337528db295 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:11 -0700 Subject: ACPI: processor: open code acpi_processor_cleanup_pdc We have the acpi_object_list * right there in acpi_processor_set_pdc() so it doesn't seem necessary for an entire helper function just to free it. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 974de4eb298..deeba22c932 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,16 +125,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - void acpi_processor_set_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -147,7 +137,10 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) return; acpi_processor_eval_pdc(pr->handle, obj_list); - acpi_processor_cleanup_pdc(pr); + + kfree(obj_list->pointer->buffer.pointer); + kfree(obj_list->pointer); + kfree(obj_list); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3 From 43bab25ced218385f7e6a076c2459ea008cfd2e1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:16 -0700 Subject: ACPI: processor: change acpi_processor_set_pdc() interface When calling _PDC, we really only need the handle to the processor to call the method; we don't look at any other parts of the struct acpi_processor * given to us. In the early path, when we walk the namespace, we are given the handle directly, so just pass it through to acpi_processor_set_pdc() without stuffing it into a wasteful struct acpi_processor allocated on the stack each time This saves 2834 bytes of stack. Update the interface accordingly. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 2 +- drivers/acpi/processor_pdc.c | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a19a4ff962e..9863c98c81b 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -763,7 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - acpi_processor_set_pdc(pr); + acpi_processor_set_pdc(pr->handle); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index deeba22c932..30e4dc0cdf3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,7 +125,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void acpi_processor_set_pdc(struct acpi_processor *pr) +void acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; @@ -136,7 +136,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - acpi_processor_eval_pdc(pr->handle, obj_list); + acpi_processor_eval_pdc(handle, obj_list); kfree(obj_list->pointer->buffer.pointer); kfree(obj_list->pointer); @@ -147,19 +147,7 @@ EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { - struct acpi_processor pr; - - pr.handle = handle; - - /* x86 implementation looks at pr.id to determine some - * CPU capabilites. We can just hard code to 0 since we're - * assuming the CPUs in the system are homogenous and all - * have the same capabilities. - */ - pr.id = 0; - - acpi_processor_set_pdc(&pr); - + acpi_processor_set_pdc(handle); return AE_OK; } -- cgit v1.2.3 From 1e9d1b13efae7e0a2705611d47ae5f07e27015f0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 19 Dec 2009 08:30:30 +0100 Subject: drivers/dma: drop unnecesary memset memset of 0 is not needed after kzalloc The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x; statement S; @@ x = kzalloc(...); if (x == NULL) S ... when != x -memset(x,0,...);// Signed-off-by: Julia Lawall Signed-off-by: Dan Williams --- drivers/dma/dw_dmac.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 2eea823516a..53bb3cac248 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1270,8 +1270,6 @@ static int __init dw_probe(struct platform_device *pdev) goto err_kfree; } - memset(dw, 0, sizeof *dw); - dw->regs = ioremap(io->start, DW_REGLEN); if (!dw->regs) { err = -ENOMEM; -- cgit v1.2.3 From 0794ec8ce327ec74416b569b8fb1951274693700 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 22 Dec 2009 21:30:59 +0100 Subject: drivers/dma: Correct use after free Move the kfree after the iounmap that refers to the same structure. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,e; identifier f; iterator I; statement S; @@ *kfree(x); ... when != &x when != x = e when != I(x,...) S *x->f // Signed-off-by: Julia Lawall Signed-off-by: Dan Williams --- drivers/dma/coh901318.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 4a99cd94536..b5f2ee0f8e2 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -1294,8 +1294,8 @@ static int __exit coh901318_remove(struct platform_device *pdev) dma_async_device_unregister(&base->dma_slave); coh901318_pool_destroy(&base->pool); free_irq(platform_get_irq(pdev, 0), base); - kfree(base); iounmap(base->virtbase); + kfree(base); release_mem_region(pdev->resource->start, resource_size(pdev->resource)); return 0; -- cgit v1.2.3 From 3b1c37cab3765b87efbd4ed40301ceaf72b9f5c2 Mon Sep 17 00:00:00 2001 From: Jonathan Woithe Date: Wed, 23 Dec 2009 09:19:42 +1030 Subject: fujitu-laptop: fix tests of acpi_evaluate_integer() return value Fix tests on return value from acpi_evaluate_integer(). Based on a patch by Roel Kluin and incorporating suggestions from Len Brown . Signed-off-by: Roel Kluin Signed-off-by: Jonathan Woithe Signed-off-by: Len Brown --- drivers/platform/x86/fujitsu-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index bcd4ba8be7d..3c2d0384b43 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -376,8 +376,8 @@ static int get_lcd_level(void) status = acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state); - if (status < 0) - return status; + if (ACPI_FAILURE(status)) + return 0; fujitsu->brightness_level = state & 0x0fffffff; @@ -398,8 +398,8 @@ static int get_max_brightness(void) status = acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state); - if (status < 0) - return status; + if (ACPI_FAILURE(status)) + return -1; fujitsu->max_brightness = state; -- cgit v1.2.3 From f5908267b67917b8cbd98b27fd2be9b5f62ec76f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 23 Dec 2009 23:22:34 +0800 Subject: hwrng: core - Fix double unlock in rng_dev_read When the loop terminates with size == 0 in rng_dev_read we will unlock the rng mutex twice. Reported-by: Dan Carpenter Signed-off-by: Herbert Xu --- drivers/char/hw_random/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index e989f67bb61..3d9c61e5acb 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -158,10 +158,11 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, goto out; } } -out_unlock: - mutex_unlock(&rng_mutex); out: return ret ? : err; +out_unlock: + mutex_unlock(&rng_mutex); + goto out; } -- cgit v1.2.3 From 4946f8353da9d3038e2a9d0295d5dfeee4cee5c5 Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Mon, 7 Dec 2009 20:42:26 +0100 Subject: [WATCHDOG] iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC add PCI ID for the Intel EP80579 (Tolapai) SoC Signed-off-by: Imre Kaloz Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index e44fbb31bc6..c8a3bec2683 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -30,6 +30,7 @@ * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) + * document number 320066-003, 320257-008: EP80597 (IICH) */ /* @@ -100,6 +101,7 @@ enum iTCO_chipsets { TCO_PCH, /* PCH Desktop Full Featured */ TCO_PCHM, /* PCH Mobile Full Featured */ TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ + TCO_EP80579, /* EP80579 */ }; static struct { @@ -143,6 +145,7 @@ static struct { {"PCH Desktop Full Featured", 2}, {"PCH Mobile Full Featured", 2}, {"PCH Mobile SFF Full Featured", 2}, + {"EP80579", 2}, {NULL, 0} }; @@ -214,6 +217,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, + { ITCO_PCI_DEVICE(0x5031, TCO_EP80579)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3 From b782a563758ac963c794d9fbaaff494140c28fd6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 4 Dec 2009 12:24:04 -0500 Subject: [WATCHDOG] use resource_size() Use resource_size(). Signed-off-by: H Hartley Sweeten Cc: Kevin Hilman Cc: Kevin Hilman Cc: Ulrik Bech Hald Cc: Henrique de Moraes Holschuh Cc: Ming Lei Cc: Vincent Sanders Acked-by: Thierry Reding Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/adx_wdt.c | 4 ++-- drivers/watchdog/at32ap700x_wdt.c | 2 +- drivers/watchdog/davinci_wdt.c | 2 +- drivers/watchdog/mpcore_wdt.c | 2 +- drivers/watchdog/mv64x60_wdt.c | 2 +- drivers/watchdog/omap_wdt.c | 9 ++++----- drivers/watchdog/pnx4008_wdt.c | 2 +- drivers/watchdog/s3c2410_wdt.c | 2 +- drivers/watchdog/txx9wdt.c | 6 ++---- 9 files changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c index 9c6594473d3..9d7d155364f 100644 --- a/drivers/watchdog/adx_wdt.c +++ b/drivers/watchdog/adx_wdt.c @@ -242,14 +242,14 @@ static int __devinit adx_wdt_probe(struct platform_device *pdev) } res = devm_request_mem_region(&pdev->dev, res->start, - res->end - res->start + 1, res->name); + resource_size(res), res->name); if (!res) { dev_err(&pdev->dev, "cannot request I/O memory region\n"); return -ENXIO; } wdt->base = devm_ioremap_nocache(&pdev->dev, res->start, - res->end - res->start + 1); + resource_size(res)); if (!wdt->base) { dev_err(&pdev->dev, "cannot remap I/O memory region\n"); return -ENXIO; diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index e8ae638e580..037847923dc 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -326,7 +326,7 @@ static int __init at32_wdt_probe(struct platform_device *pdev) return -ENOMEM; } - wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); + wdt->regs = ioremap(regs->start, resource_size(regs)); if (!wdt->regs) { ret = -ENOMEM; dev_dbg(&pdev->dev, "could not map I/O memory\n"); diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 9d7520fa9e9..887136de185 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -221,7 +221,7 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = res->end - res->start + 1; + size = resource_size(res); wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 83fa34b214b..a2dc07c2ed4 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -350,7 +350,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) ret = -ENXIO; goto err_free; } - wdt->base = ioremap(res->start, res->end - res->start + 1); + wdt->base = ioremap(res->start, resource_size(res)); if (!wdt->base) { ret = -ENOMEM; goto err_free; diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index acf589dc057..a51dbe4c43d 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c @@ -275,7 +275,7 @@ static int __devinit mv64x60_wdt_probe(struct platform_device *dev) if (!r) return -ENODEV; - mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1); + mv64x60_wdt_regs = ioremap(r->start, resource_size(r)); if (mv64x60_wdt_regs == NULL) return -ENOMEM; diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 429ea99eaee..c6aaf284574 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -277,8 +277,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) goto err_busy; } - mem = request_mem_region(res->start, res->end - res->start + 1, - pdev->name); + mem = request_mem_region(res->start, resource_size(res), pdev->name); if (!mem) { ret = -EBUSY; goto err_busy; @@ -306,7 +305,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) goto err_clk; } - wdev->base = ioremap(res->start, res->end - res->start + 1); + wdev->base = ioremap(res->start, resource_size(res)); if (!wdev->base) { ret = -ENOMEM; goto err_ioremap; @@ -358,7 +357,7 @@ err_clk: kfree(wdev); err_kzalloc: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); err_busy: err_get_resource: @@ -383,7 +382,7 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) return -ENOENT; misc_deregister(&(wdev->omap_wdt_miscdev)); - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); clk_put(wdev->ick); diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 4d227b15200..430a5848a9a 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -264,7 +264,7 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = res->end - res->start + 1; + size = resource_size(res); wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 85b93e15d01..8760a26ab2a 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -421,7 +421,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = (res->end - res->start) + 1; + size = resource_size(res); wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { dev_err(dev, "failed to get memory region\n"); diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 6adab77fbbb..d635566e930 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -214,12 +214,10 @@ static int __init txx9wdt_probe(struct platform_device *dev) res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) goto exit_busy; - if (!devm_request_mem_region(&dev->dev, - res->start, res->end - res->start + 1, + if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res), "txx9wdt")) goto exit_busy; - txx9wdt_reg = devm_ioremap(&dev->dev, - res->start, res->end - res->start + 1); + txx9wdt_reg = devm_ioremap(&dev->dev, res->start, resource_size(res)); if (!txx9wdt_reg) goto exit_busy; -- cgit v1.2.3 From 9dc130fccb874f2959ef313d7922d306dc6d4f75 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 23 Dec 2009 17:04:11 +0800 Subject: ACPI: fix OSC regression that caused aer and pciehp not to load Executing _OSC returns a buffer, which has an acpi object in it. Don't directly returns the buffer, instead, we return the acpi object's buffer. This fixes a regression since caller of acpi_run_osc expects an acpi object's buffer returned. Tested-by: Yinghai Lu Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/bus.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f12..0c1ad3105da 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) union acpi_object *out_obj; u8 uuid[16]; u32 errors; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; if (!context) return AE_ERROR; @@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) in_params[3].buffer.length = context->cap.length; in_params[3].buffer.pointer = context->cap.pointer; - status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + status = acpi_evaluate_object(handle, "_OSC", &input, &output); if (ACPI_FAILURE(status)) return status; - /* return buffer should have the same length as cap buffer */ - if (context->ret.length != context->cap.length) + if (!output.length) return AE_NULL_OBJECT; - out_obj = context->ret.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER + || out_obj->buffer.length != context->cap.length) { acpi_print_osc_error(handle, context, "_OSC evaluation returned wrong type"); status = AE_TYPE; @@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) goto out_kfree; } out_success: - return AE_OK; + context->ret.length = out_obj->buffer.length; + context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); + if (!context->ret.pointer) { + status = AE_NO_MEMORY; + goto out_kfree; + } + memcpy(context->ret.pointer, out_obj->buffer.pointer, + context->ret.length); + status = AE_OK; out_kfree: - kfree(context->ret.pointer); - context->ret.pointer = NULL; + kfree(output.pointer); + if (status != AE_OK) + context->ret.pointer = NULL; return status; } EXPORT_SYMBOL(acpi_run_osc); -- cgit v1.2.3 From ac07fb4dc1908d300f50fa711982c9d750eb59f7 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 21 Dec 2009 09:28:30 -0500 Subject: i2c-bfin-twi: fix CLKDIV calculation Calculation of the CLKDIV speed setting should be done using base 10 math rather than base 2. We also avoid exceeding the spec due to integer truncation and a 50% duty cycle. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-bfin-twi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index b309ac2c3d5..fe3fb567317 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -693,13 +693,13 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) } /* Set TWI internal clock as 10MHz */ - write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F); + write_CONTROL(iface, ((get_sclk() / 1000 / 1000 + 5) / 10) & 0x7F); /* * We will not end up with a CLKDIV=0 because no one will specify - * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100) + * 20kHz SCL or less in Kconfig now. (5 * 1000 / 20 = 250) */ - clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ; + clkhilow = ((10 * 1000 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) + 1) / 2; /* Set Twi interface clock as specified */ write_CLKDIV(iface, (clkhilow << 8) | clkhilow); -- cgit v1.2.3 From 07ac31f6f4cd558e53f6705dbe3033a7f0237eb8 Mon Sep 17 00:00:00 2001 From: Cory Maccarrone Date: Tue, 22 Dec 2009 18:06:13 -0700 Subject: i2c-omap: Don't write IE state in unidle if 0 Commit ef871432... (i2c-omap: OMAP3: PM: (re)init for every transfer to support off-mode) introduced a change which make the dev->iestate contents be written to the OMAP_I2C_IE_REG every time omap_i2c_unidle is called. Previously, the state was only written if it wasn't equal to zero. In omap_i2c_probe, omap_i2c_unidle() is called prior to omap_i2c_init(), in which case dev->iestate has not yet been initialized and will be set to zero. Having this value written to the registers causes deadlock while booting. As such, this change restores the original functionality. Signed-off-by: Cory Maccarrone Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 75bf3ad1809..a64a192c44a 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -247,7 +247,13 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); } dev->idle = 0; - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); + + /* + * Don't write to this register if the IE state is 0 as it can + * cause deadlock. + */ + if (dev->iestate) + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); } static void omap_i2c_idle(struct omap_i2c_dev *dev) -- cgit v1.2.3 From 57eb81b14e35a14df64ac3597bc90c26ce04a9b4 Mon Sep 17 00:00:00 2001 From: Manjunatha GK Date: Fri, 11 Dec 2009 11:09:08 +0530 Subject: i2c-omap: OMAP3: Fix I2C lockup during timeout/error cases Current OMAP3 I2C driver code does not follow the correct sequence for soft reset. Due to this, lock up issues are reported during timeout/error cases. This patch fixes above issue by disabling I2C controller as per OMAP3430 TRM for soft reset. As per TRM, I2C controller needs to be disabled as a first step during soft reset. Here is correct soft reset sequence: a. Ensure that the module is disabled (clear the I2Ci.I2C_CON[15] I2C_EN bit to 0). b. Set the I2Ci.I2C_SYSC[1] SRST bit to 1. c. Enable the module by setting I2Ci.I2C_CON[15] I2C_EN bit to 1. d. Check the I2Ci.I2C_SYSS[0] RDONE bit until it is set to 1 to indicate the software reset is complete. Tested on Zoom2, Zoom3, 3430SDP and 3630SDP Signed-off-by: Manjunatha GK Signed-off-by: George, Harith Acked-by: Varadarajan, Charu Latha Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a64a192c44a..0037e31076b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -286,6 +286,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) unsigned long internal_clk = 0; if (dev->rev >= OMAP_I2C_REV_2) { + /* Disable I2C controller before soft reset */ + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, + omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & + ~(OMAP_I2C_CON_EN)); + omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); /* For some reason we need to set the EN bit before the * reset done bit gets set. */ -- cgit v1.2.3 From d5a664a311c1957a75bec1808cae0f10d606c378 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 17 Dec 2009 00:08:35 +0900 Subject: sony-laptop: rfkill support for newer models Vaio Type X and possibly other new models use F135 as the radio frequency controlling function attached to the SNC device. In the indexed table this corresponds to 0x0135 (surpise!). Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9710f70040b..1144686a33f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -131,6 +131,7 @@ enum sony_nc_rfkill { N_SONY_RFKILL, }; +static int sony_rfkill_handle; static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; static void sony_nc_rfkill_update(void); @@ -965,7 +966,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) else sony_laptop_report_input_event(ev); } - } else if (sony_find_snc_handle(0x124) == ev) { + } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) { sony_nc_rfkill_update(); return; } @@ -1071,7 +1072,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) if (!blocked) argument |= 0xff0000; - return sony_call_snc_handle(0x124, argument, &result); + return sony_call_snc_handle(sony_rfkill_handle, argument, &result); } static const struct rfkill_ops sony_rfkill_ops = { @@ -1114,7 +1115,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, if (!rfk) return -ENOMEM; - sony_call_snc_handle(0x124, 0x200, &result); + sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1); rfkill_set_hw_state(rfk, hwblock); @@ -1133,7 +1134,7 @@ static void sony_nc_rfkill_update() int result; bool hwblock; - sony_call_snc_handle(0x124, 0x200, &result); + sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1); for (i = 0; i < N_SONY_RFKILL; i++) { @@ -1149,7 +1150,7 @@ static void sony_nc_rfkill_update() continue; } - sony_call_snc_handle(0x124, argument, &result); + sony_call_snc_handle(sony_rfkill_handle, argument, &result); rfkill_set_states(sony_rfkill_devices[i], !(result & 0xf), false); } @@ -1159,10 +1160,15 @@ static int sony_nc_rfkill_setup(struct acpi_device *device) { int result, ret; - if (sony_find_snc_handle(0x124) == -1) - return -1; + if (sony_find_snc_handle(0x124) == -1) { + if (sony_find_snc_handle(0x135) == -1) + return -1; + else + sony_rfkill_handle = 0x135; + } else + sony_rfkill_handle = 0x124; - ret = sony_call_snc_handle(0x124, 0xb00, &result); + ret = sony_call_snc_handle(sony_rfkill_handle, 0xb00, &result); if (ret) { printk(KERN_INFO DRV_PFX "Unable to enumerate rfkill devices: %x\n", ret); -- cgit v1.2.3 From 528809c35faebd8c50a4722c85ab8610725875cc Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 17 Dec 2009 00:08:36 +0900 Subject: sony-laptop: enumerate rfkill devices using SN06 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SN06 makes sure we get back a longer buffer which seems to be necessary going forward as the SNC devices describes more and more devices (or features more precisely). Moreover SN06 should be called with only the descriptor offset to make sure we hit the rfkill controlling function (F124 or F135) with a 0 argument to get a full list of features. Signed-off-by: Mattia Dongili Tested-by: Miguel Rodríguez Pérez Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 76 ++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 1144686a33f..49f3fe0ac59 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1156,35 +1156,73 @@ static void sony_nc_rfkill_update() } } -static int sony_nc_rfkill_setup(struct acpi_device *device) +static void sony_nc_rfkill_setup(struct acpi_device *device) { - int result, ret; + int offset; + u8 dev_code, i; + acpi_status status; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *device_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (sony_find_snc_handle(0x124) == -1) { - if (sony_find_snc_handle(0x135) == -1) - return -1; + offset = sony_find_snc_handle(0x124); + if (offset == -1) { + offset = sony_find_snc_handle(0x135); + if (offset == -1) + return; else sony_rfkill_handle = 0x135; } else sony_rfkill_handle = 0x124; + dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); - ret = sony_call_snc_handle(sony_rfkill_handle, 0xb00, &result); - if (ret) { - printk(KERN_INFO DRV_PFX - "Unable to enumerate rfkill devices: %x\n", ret); - return ret; + /* need to read the whole buffer returned by the acpi call to SN06 + * here otherwise we may miss some features + */ + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) { + dprintk("Radio device enumeration failed\n"); + return; } - if (result & 0x1) - sony_nc_setup_rfkill(device, SONY_WIFI); - if (result & 0x2) - sony_nc_setup_rfkill(device, SONY_BLUETOOTH); - if (result & 0x1c) - sony_nc_setup_rfkill(device, SONY_WWAN); - if (result & 0x20) - sony_nc_setup_rfkill(device, SONY_WIMAX); + device_enum = (union acpi_object *) buffer.pointer; + if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { + printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", + device_enum->type); + goto out_no_enum; + } - return 0; + /* the buffer is filled with magic numbers describing the devices + * available, 0xff terminates the enumeration + */ + while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && + i < device_enum->buffer.length) { + i++; + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); + + if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) + sony_nc_setup_rfkill(device, SONY_WIFI); + + if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) + sony_nc_setup_rfkill(device, SONY_BLUETOOTH); + + if ((0xf0 & dev_code) == 0x20 && + !sony_rfkill_devices[SONY_WWAN]) + sony_nc_setup_rfkill(device, SONY_WWAN); + + if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) + sony_nc_setup_rfkill(device, SONY_WIMAX); + } + +out_no_enum: + kfree(buffer.pointer); + return; } static int sony_nc_add(struct acpi_device *device) -- cgit v1.2.3 From 2370b5ed03030d554adb345778d5edecab7a510c Mon Sep 17 00:00:00 2001 From: "Carlos R. Mafra" Date: Tue, 22 Dec 2009 13:45:39 -0800 Subject: ACPI: do not select ACPI_DOCK from ATA_ACPI In March 2008 commit 0ac4a3c2fbbcadc3e96e4dc47d4ae802d66e6f67 ("ACPI: fix ATA_ACPI build") made CONFIG_ACPI_DOCK be selected by CONFIG_ATA_ACPI because of a build error when CONFIG_ATA_ACPI=y and CONFIG_ACPI_DOCK=m. However, in September 2008 commit 898b054f3eec5921320ae8614b5bdd7b07ea5b43 ("dock: make dock driver not a module") removed the possibility of having CONFIG_ACPI_DOCK=m and therefore there is no need for selecting it when CONFIG_ATA_ACPI=y. This makes the kernel ~5 Kb smaller for people who don't have a dock by allowing them to not have ACPI_DOCK compiled-in because of ATA_ACPI=y. Signed-off-by: Carlos R. Mafra Cc: Shaohua Li Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/ata/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 85844d05384..56c6374a398 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -40,7 +40,6 @@ config ATA_VERBOSE_ERROR config ATA_ACPI bool "ATA ACPI Support" depends on ACPI && PCI - select ACPI_DOCK default y help This option adds support for ATA-related ACPI objects. -- cgit v1.2.3 From ff93be5dea548f16dcfe7b73ce5df7666efba92d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 21 Dec 2009 16:20:01 -0800 Subject: asus_acpi: convert to seq_file Signed-off-by: Alexey Dobriyan Cc: Corentin Chary Cc: Karol Kozimor Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/asus_acpi.c | 321 +++++++++++++++++++++++---------------- 1 file changed, 194 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 0c9c53111a2..c1d2aeeea94 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -513,26 +514,12 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val) return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER); } -/* - * We write our info in page, we begin at offset off and cannot write more - * than count bytes. We set eof to 1 if we handle those 2 values. We return the - * number of bytes written in page - */ -static int -proc_read_info(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int asus_info_proc_show(struct seq_file *m, void *v) { - int len = 0; int temp; - char buf[16]; /* enough for all info */ - /* - * We use the easy way, we don't care of off and count, - * so we don't set eof to 1 - */ - len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); - len += sprintf(page + len, "Model reference : %s\n", - hotk->methods->name); + seq_printf(m, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); + seq_printf(m, "Model reference : %s\n", hotk->methods->name); /* * The SFUN method probably allows the original driver to get the list * of features supported by a given model. For now, 0x0100 or 0x0800 @@ -540,8 +527,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, * The significance of others is yet to be found. */ if (read_acpi_int(hotk->handle, "SFUN", &temp)) - len += - sprintf(page + len, "SFUN value : 0x%04x\n", temp); + seq_printf(m, "SFUN value : 0x%04x\n", temp); /* * Another value for userspace: the ASYM method returns 0x02 for * battery low and 0x04 for battery critical, its readings tend to be @@ -550,30 +536,34 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, * silently ignored. */ if (read_acpi_int(hotk->handle, "ASYM", &temp)) - len += - sprintf(page + len, "ASYM value : 0x%04x\n", temp); + seq_printf(m, "ASYM value : 0x%04x\n", temp); if (asus_info) { - snprintf(buf, 16, "%d", asus_info->length); - len += sprintf(page + len, "DSDT length : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->checksum); - len += sprintf(page + len, "DSDT checksum : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->revision); - len += sprintf(page + len, "DSDT revision : %s\n", buf); - snprintf(buf, 7, "%s", asus_info->oem_id); - len += sprintf(page + len, "OEM id : %s\n", buf); - snprintf(buf, 9, "%s", asus_info->oem_table_id); - len += sprintf(page + len, "OEM table id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->oem_revision); - len += sprintf(page + len, "OEM revision : 0x%s\n", buf); - snprintf(buf, 5, "%s", asus_info->asl_compiler_id); - len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); - len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); + seq_printf(m, "DSDT length : %d\n", asus_info->length); + seq_printf(m, "DSDT checksum : %d\n", asus_info->checksum); + seq_printf(m, "DSDT revision : %d\n", asus_info->revision); + seq_printf(m, "OEM id : %.*s\n", ACPI_OEM_ID_SIZE, asus_info->oem_id); + seq_printf(m, "OEM table id : %.*s\n", ACPI_OEM_TABLE_ID_SIZE, asus_info->oem_table_id); + seq_printf(m, "OEM revision : 0x%x\n", asus_info->oem_revision); + seq_printf(m, "ASL comp vendor id : %.*s\n", ACPI_NAME_SIZE, asus_info->asl_compiler_id); + seq_printf(m, "ASL comp revision : 0x%x\n", asus_info->asl_compiler_revision); } - return len; + return 0; +} + +static int asus_info_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, asus_info_proc_show, NULL); } +static const struct file_operations asus_info_proc_fops = { + .owner = THIS_MODULE, + .open = asus_info_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * /proc handlers * We write our info in page, we begin at offset off and cannot write more @@ -639,34 +629,48 @@ write_led(const char __user *buffer, unsigned long count, /* * Proc handlers for MLED */ -static int -proc_read_mled(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int mled_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", - read_led(hotk->methods->mled_status, MLED_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->mled_status, MLED_ON)); + return 0; } -static int -proc_write_mled(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int mled_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mled_proc_show, NULL); +} + +static ssize_t mled_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1); } +static const struct file_operations mled_proc_fops = { + .owner = THIS_MODULE, + .open = mled_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = mled_proc_write, +}; + /* * Proc handlers for LED display */ -static int -proc_read_ledd(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int ledd_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "0x%08x\n", hotk->ledd_status); + seq_printf(m, "0x%08x\n", hotk->ledd_status); + return 0; } -static int -proc_write_ledd(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int ledd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ledd_proc_show, NULL); +} + +static ssize_t ledd_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -682,61 +686,104 @@ proc_write_ledd(struct file *file, const char __user *buffer, return rv; } +static const struct file_operations ledd_proc_fops = { + .owner = THIS_MODULE, + .open = ledd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = ledd_proc_write, +}; + /* * Proc handlers for WLED */ -static int -proc_read_wled(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int wled_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", - read_led(hotk->methods->wled_status, WLED_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->wled_status, WLED_ON)); + return 0; } -static int -proc_write_wled(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int wled_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, wled_proc_show, NULL); +} + +static ssize_t wled_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0); } +static const struct file_operations wled_proc_fops = { + .owner = THIS_MODULE, + .open = wled_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = wled_proc_write, +}; + /* * Proc handlers for Bluetooth */ -static int -proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int bluetooth_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", read_led(hotk->methods->bt_status, BT_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->bt_status, BT_ON)); + return 0; } -static int -proc_write_bluetooth(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int bluetooth_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, bluetooth_proc_show, NULL); +} + +static ssize_t bluetooth_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { /* Note: mt_bt_switch controls both internal Bluetooth adapter's presence and its LED */ return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0); } +static const struct file_operations bluetooth_proc_fops = { + .owner = THIS_MODULE, + .open = bluetooth_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = bluetooth_proc_write, +}; + /* * Proc handlers for TLED */ -static int -proc_read_tled(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int tled_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", - read_led(hotk->methods->tled_status, TLED_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->tled_status, TLED_ON)); + return 0; } -static int -proc_write_tled(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int tled_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, tled_proc_show, NULL); +} + +static ssize_t tled_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0); } +static const struct file_operations tled_proc_fops = { + .owner = THIS_MODULE, + .open = tled_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = tled_proc_write, +}; + static int get_lcd_state(void) { int lcd = 0; @@ -829,16 +876,19 @@ static int set_lcd_state(int value) } -static int -proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int lcd_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", get_lcd_state()); + seq_printf(m, "%d\n", get_lcd_state()); + return 0; } -static int -proc_write_lcd(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int lcd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, lcd_proc_show, NULL); +} + +static ssize_t lcd_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -848,6 +898,15 @@ proc_write_lcd(struct file *file, const char __user *buffer, return rv; } +static const struct file_operations lcd_proc_fops = { + .owner = THIS_MODULE, + .open = lcd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = lcd_proc_write, +}; + static int read_brightness(struct backlight_device *bd) { int value; @@ -907,16 +966,19 @@ static int set_brightness_status(struct backlight_device *bd) return set_brightness(bd->props.brightness); } -static int -proc_read_brn(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int brn_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", read_brightness(NULL)); + seq_printf(m, "%d\n", read_brightness(NULL)); + return 0; } -static int -proc_write_brn(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int brn_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, brn_proc_show, NULL); +} + +static ssize_t brn_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -929,6 +991,15 @@ proc_write_brn(struct file *file, const char __user *buffer, return rv; } +static const struct file_operations brn_proc_fops = { + .owner = THIS_MODULE, + .open = brn_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = brn_proc_write, +}; + static void set_display(int value) { /* no sanity check needed for now */ @@ -942,9 +1013,7 @@ static void set_display(int value) * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in proc_write_disp() */ -static int -proc_read_disp(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int disp_proc_show(struct seq_file *m, void *v) { int value = 0; @@ -952,7 +1021,13 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); value &= 0x07; /* needed for some models, shouldn't hurt others */ - return sprintf(page, "%d\n", value); + seq_printf(m, "%d\n", value); + return 0; +} + +static int disp_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, disp_proc_show, NULL); } /* @@ -961,9 +1036,8 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, * (bitwise) of these will suffice. I never actually tested 3 displays hooked * up simultaneously, so be warned. See the acpi4asus README for more info. */ -static int -proc_write_disp(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t disp_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -973,25 +1047,27 @@ proc_write_disp(struct file *file, const char __user *buffer, return rv; } -typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, - int *eof, void *data); -typedef int (proc_writefunc) (struct file *file, const char __user *buffer, - unsigned long count, void *data); +static const struct file_operations disp_proc_fops = { + .owner = THIS_MODULE, + .open = disp_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = disp_proc_write, +}; static int -asus_proc_add(char *name, proc_writefunc *writefunc, - proc_readfunc *readfunc, mode_t mode, +asus_proc_add(char *name, const struct file_operations *proc_fops, mode_t mode, struct acpi_device *device) { - struct proc_dir_entry *proc = - create_proc_entry(name, mode, acpi_device_dir(device)); + struct proc_dir_entry *proc; + + proc = proc_create_data(name, mode, acpi_device_dir(device), + proc_fops, acpi_driver_data(device)); if (!proc) { printk(KERN_WARNING " Unable to create %s fs entry\n", name); return -1; } - proc->write_proc = writefunc; - proc->read_proc = readfunc; - proc->data = acpi_driver_data(device); proc->uid = asus_uid; proc->gid = asus_gid; return 0; @@ -1020,10 +1096,9 @@ static int asus_hotk_add_fs(struct acpi_device *device) if (!acpi_device_dir(device)) return -ENODEV; - proc = create_proc_entry(PROC_INFO, mode, acpi_device_dir(device)); + proc = proc_create(PROC_INFO, mode, acpi_device_dir(device), + &asus_info_proc_fops); if (proc) { - proc->read_proc = proc_read_info; - proc->data = acpi_driver_data(device); proc->uid = asus_uid; proc->gid = asus_gid; } else { @@ -1032,28 +1107,23 @@ static int asus_hotk_add_fs(struct acpi_device *device) } if (hotk->methods->mt_wled) { - asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled, - mode, device); + asus_proc_add(PROC_WLED, &wled_proc_fops, mode, device); } if (hotk->methods->mt_ledd) { - asus_proc_add(PROC_LEDD, &proc_write_ledd, &proc_read_ledd, - mode, device); + asus_proc_add(PROC_LEDD, &ledd_proc_fops, mode, device); } if (hotk->methods->mt_mled) { - asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, - mode, device); + asus_proc_add(PROC_MLED, &mled_proc_fops, mode, device); } if (hotk->methods->mt_tled) { - asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled, - mode, device); + asus_proc_add(PROC_TLED, &tled_proc_fops, mode, device); } if (hotk->methods->mt_bt_switch) { - asus_proc_add(PROC_BT, &proc_write_bluetooth, - &proc_read_bluetooth, mode, device); + asus_proc_add(PROC_BT, &bluetooth_proc_fops, mode, device); } /* @@ -1061,19 +1131,16 @@ static int asus_hotk_add_fs(struct acpi_device *device) * accessible from the keyboard */ if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) { - asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, - device); + asus_proc_add(PROC_LCD, &lcd_proc_fops, mode, device); } if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_set)) { - asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, - device); + asus_proc_add(PROC_BRN, &brn_proc_fops, mode, device); } if (hotk->methods->display_set) { - asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, - mode, device); + asus_proc_add(PROC_DISP, &disp_proc_fops, mode, device); } return 0; -- cgit v1.2.3 From 936c8bcd7f5b418d0e040be539ceb4d2ac3bc0b8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 21 Dec 2009 16:20:02 -0800 Subject: toshiba_acpi: convert to seq_file Signed-off-by: Alexey Dobriyan Cc: John W. Linville Cc: Johannes Berg Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/toshiba_acpi.c | 259 ++++++++++++++++++++---------------- 1 file changed, 147 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 51c0a8bee41..77bf5d8f893 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -357,63 +358,6 @@ static int force_fan; static int last_key_event; static int key_event_valid; -typedef struct _ProcItem { - const char *name; - char *(*read_func) (char *); - unsigned long (*write_func) (const char *, unsigned long); -} ProcItem; - -/* proc file handlers - */ - -static int -dispatch_read(char *page, char **start, off_t off, int count, int *eof, - ProcItem * item) -{ - char *p = page; - int len; - - if (off == 0) - p = item->read_func(p); - - /* ISSUE: I don't understand this code */ - len = (p - page); - if (len <= off + count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -static int -dispatch_write(struct file *file, const char __user * buffer, - unsigned long count, ProcItem * item) -{ - int result; - char *tmp_buffer; - - /* Arg buffer points to userspace memory, which can't be accessed - * directly. Since we're making a copy, zero-terminate the - * destination so that sscanf can be used on it safely. - */ - tmp_buffer = kmalloc(count + 1, GFP_KERNEL); - if (!tmp_buffer) - return -ENOMEM; - - if (copy_from_user(tmp_buffer, buffer, count)) { - result = -EFAULT; - } else { - tmp_buffer[count] = 0; - result = item->write_func(tmp_buffer, count); - } - kfree(tmp_buffer); - return result; -} - static int get_lcd(struct backlight_device *bd) { u32 hci_result; @@ -426,19 +370,24 @@ static int get_lcd(struct backlight_device *bd) return -EFAULT; } -static char *read_lcd(char *p) +static int lcd_proc_show(struct seq_file *m, void *v) { int value = get_lcd(NULL); if (value >= 0) { - p += sprintf(p, "brightness: %d\n", value); - p += sprintf(p, "brightness_levels: %d\n", + seq_printf(m, "brightness: %d\n", value); + seq_printf(m, "brightness_levels: %d\n", HCI_LCD_BRIGHTNESS_LEVELS); } else { printk(MY_ERR "Error reading LCD brightness\n"); } - return p; + return 0; +} + +static int lcd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, lcd_proc_show, NULL); } static int set_lcd(int value) @@ -458,12 +407,20 @@ static int set_lcd_status(struct backlight_device *bd) return set_lcd(bd->props.brightness); } -static unsigned long write_lcd(const char *buffer, unsigned long count) +static ssize_t lcd_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { + char cmd[42]; + size_t len; int value; int ret; - if (sscanf(buffer, " brightness : %i", &value) == 1 && + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; + cmd[len] = '\0'; + + if (sscanf(cmd, " brightness : %i", &value) == 1 && value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { ret = set_lcd(value); if (ret == 0) @@ -474,7 +431,16 @@ static unsigned long write_lcd(const char *buffer, unsigned long count) return ret; } -static char *read_video(char *p) +static const struct file_operations lcd_proc_fops = { + .owner = THIS_MODULE, + .open = lcd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = lcd_proc_write, +}; + +static int video_proc_show(struct seq_file *m, void *v) { u32 hci_result; u32 value; @@ -484,18 +450,25 @@ static char *read_video(char *p) int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; - p += sprintf(p, "lcd_out: %d\n", is_lcd); - p += sprintf(p, "crt_out: %d\n", is_crt); - p += sprintf(p, "tv_out: %d\n", is_tv); + seq_printf(m, "lcd_out: %d\n", is_lcd); + seq_printf(m, "crt_out: %d\n", is_crt); + seq_printf(m, "tv_out: %d\n", is_tv); } else { printk(MY_ERR "Error reading video out status\n"); } - return p; + return 0; } -static unsigned long write_video(const char *buffer, unsigned long count) +static int video_proc_open(struct inode *inode, struct file *file) { + return single_open(file, video_proc_show, NULL); +} + +static ssize_t video_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + char *cmd, *buffer; int value; int remain = count; int lcd_out = -1; @@ -504,6 +477,17 @@ static unsigned long write_video(const char *buffer, unsigned long count) u32 hci_result; u32 video_out; + cmd = kmalloc(count + 1, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + if (copy_from_user(cmd, buf, count)) { + kfree(cmd); + return -EFAULT; + } + cmd[count] = '\0'; + + buffer = cmd; + /* scan expression. Multiple expressions may be delimited with ; * * NOTE: to keep scanning simple, invalid fields are ignored @@ -523,6 +507,8 @@ static unsigned long write_video(const char *buffer, unsigned long count) while (remain && *(buffer - 1) != ';'); } + kfree(cmd); + hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result); if (hci_result == HCI_SUCCESS) { unsigned int new_video_out = video_out; @@ -543,28 +529,50 @@ static unsigned long write_video(const char *buffer, unsigned long count) return count; } -static char *read_fan(char *p) +static const struct file_operations video_proc_fops = { + .owner = THIS_MODULE, + .open = video_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = video_proc_write, +}; + +static int fan_proc_show(struct seq_file *m, void *v) { u32 hci_result; u32 value; hci_read1(HCI_FAN, &value, &hci_result); if (hci_result == HCI_SUCCESS) { - p += sprintf(p, "running: %d\n", (value > 0)); - p += sprintf(p, "force_on: %d\n", force_fan); + seq_printf(m, "running: %d\n", (value > 0)); + seq_printf(m, "force_on: %d\n", force_fan); } else { printk(MY_ERR "Error reading fan status\n"); } - return p; + return 0; +} + +static int fan_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, fan_proc_show, NULL); } -static unsigned long write_fan(const char *buffer, unsigned long count) +static ssize_t fan_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { + char cmd[42]; + size_t len; int value; u32 hci_result; - if (sscanf(buffer, " force_on : %i", &value) == 1 && + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; + cmd[len] = '\0'; + + if (sscanf(cmd, " force_on : %i", &value) == 1 && value >= 0 && value <= 1) { hci_write1(HCI_FAN, value, &hci_result); if (hci_result != HCI_SUCCESS) @@ -578,7 +586,16 @@ static unsigned long write_fan(const char *buffer, unsigned long count) return count; } -static char *read_keys(char *p) +static const struct file_operations fan_proc_fops = { + .owner = THIS_MODULE, + .open = fan_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = fan_proc_write, +}; + +static int keys_proc_show(struct seq_file *m, void *v) { u32 hci_result; u32 value; @@ -602,18 +619,30 @@ static char *read_keys(char *p) } } - p += sprintf(p, "hotkey_ready: %d\n", key_event_valid); - p += sprintf(p, "hotkey: 0x%04x\n", last_key_event); + seq_printf(m, "hotkey_ready: %d\n", key_event_valid); + seq_printf(m, "hotkey: 0x%04x\n", last_key_event); +end: + return 0; +} - end: - return p; +static int keys_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, keys_proc_show, NULL); } -static unsigned long write_keys(const char *buffer, unsigned long count) +static ssize_t keys_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { + char cmd[42]; + size_t len; int value; - if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 && value == 0) { + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; + cmd[len] = '\0'; + + if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) { key_event_valid = 0; } else { return -EINVAL; @@ -622,52 +651,58 @@ static unsigned long write_keys(const char *buffer, unsigned long count) return count; } -static char *read_version(char *p) +static const struct file_operations keys_proc_fops = { + .owner = THIS_MODULE, + .open = keys_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = keys_proc_write, +}; + +static int version_proc_show(struct seq_file *m, void *v) { - p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION); - p += sprintf(p, "proc_interface: %d\n", - PROC_INTERFACE_VERSION); - return p; + seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION); + seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION); + return 0; } +static int version_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, version_proc_show, PDE(inode)->data); +} + +static const struct file_operations version_proc_fops = { + .owner = THIS_MODULE, + .open = version_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* proc and module init */ #define PROC_TOSHIBA "toshiba" -static ProcItem proc_items[] = { - {"lcd", read_lcd, write_lcd}, - {"video", read_video, write_video}, - {"fan", read_fan, write_fan}, - {"keys", read_keys, write_keys}, - {"version", read_version, NULL}, - {NULL} -}; - static acpi_status __init add_device(void) { - struct proc_dir_entry *proc; - ProcItem *item; - - for (item = proc_items; item->name; ++item) { - proc = create_proc_read_entry(item->name, - S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, - (read_proc_t *) dispatch_read, - item); - if (proc && item->write_func) - proc->write_proc = (write_proc_t *) dispatch_write; - } + proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops); + proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops); + proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops); + proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops); + proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops); return AE_OK; } static acpi_status remove_device(void) { - ProcItem *item; - - for (item = proc_items; item->name; ++item) - remove_proc_entry(item->name, toshiba_proc_dir); + remove_proc_entry("lcd", toshiba_proc_dir); + remove_proc_entry("video", toshiba_proc_dir); + remove_proc_entry("fan", toshiba_proc_dir); + remove_proc_entry("keys", toshiba_proc_dir); + remove_proc_entry("version", toshiba_proc_dir); return AE_OK; } -- cgit v1.2.3 From bdc731bc5fcd1794e9ac8ac80c389d302381c123 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Mon, 21 Dec 2009 16:20:04 -0800 Subject: acerhdf: limit modalias matching to supported BugLink: https://bugs.launchpad.net/ubuntu/+bug/435958 The module alias currently matches any Acer computer but when loaded the BIOS checks will only succeed on Aspire One models. This causes a invalid BIOS warning for all other models (seen on Aspire 4810T). This is not fatal but worries users that see this message. Limiting the moule alias to models starting with AOA or DOA for Packard Bell. Signed-off-by: Stefan Bader Acked-by: Borislav Petkov Acked-by: Peter Feuerer Cc: Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/acerhdf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 79b15b9d9cf..007bc55b986 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -640,9 +640,10 @@ static void __exit acerhdf_exit(void) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Peter Feuerer"); MODULE_DESCRIPTION("Aspire One temperature and fan driver"); -MODULE_ALIAS("dmi:*:*Acer*:*:"); -MODULE_ALIAS("dmi:*:*Gateway*:*:"); -MODULE_ALIAS("dmi:*:*Packard Bell*:*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); module_init(acerhdf_init); module_exit(acerhdf_exit); -- cgit v1.2.3 From 94219d798e65dff1dac5f8f36f03a9bdb3105f91 Mon Sep 17 00:00:00 2001 From: Peter Feuerer Date: Mon, 21 Dec 2009 16:20:05 -0800 Subject: acerhdf: add new BIOS versions Add new BIOS versions for following netbooks: Aspire 1810xx, Packard Bell DOTMU. Signed-off-by: Peter Feuerer Cc: Borislav Petkov Cc: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/acerhdf.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 007bc55b986..a97fc4a7c60 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.20" +#define DRV_VER "0.5.21" /* * According to the Atom N270 datasheet, @@ -156,7 +156,13 @@ static const struct bios_settings_t bios_tbl[] = { {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, /* Acer 1410 */ {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - /* special BIOS / other */ + {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + /* Acer 1810xx */ + {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + /* Gateway */ {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, {"Gateway ", "LT31 ", "v1.3103 ", 0x55, 0x58, @@ -165,10 +171,13 @@ static const struct bios_settings_t bios_tbl[] = { {0x10, 0x0f, 0x00} }, {"Gateway ", "LT31 ", "v1.3302 ", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + /* Packard Bell */ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, /* pewpew-terminator */ {"", "", "", 0, 0, {0, 0, 0} } }; @@ -641,9 +650,13 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Peter Feuerer"); MODULE_DESCRIPTION("Aspire One temperature and fan driver"); MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:"); MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:"); module_init(acerhdf_init); module_exit(acerhdf_exit); -- cgit v1.2.3 From dcbfb8156a2149fd6358a377aa9400e28ef43800 Mon Sep 17 00:00:00 2001 From: Peter Feuerer Date: Mon, 21 Dec 2009 16:20:06 -0800 Subject: drivers/platform/x86/acerhdf.c: check BIOS information whether it begins with string of table BIOS information is now checked whether it begins with the strings stored in the BIOS table. Previous method did a strcmp, what lead to problems if BIOS information has appended whitespaces. Signed-off-by: Peter Feuerer Cc: Borislav Petkov Cc: Andreas Mohr Cc: Ingo Molnar Cc: Thomas Gleixner Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/acerhdf.c | 46 +++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index a97fc4a7c60..7b2384d674d 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.21" +#define DRV_VER "0.5.22" /* * According to the Atom N270 datasheet, @@ -165,12 +165,9 @@ static const struct bios_settings_t bios_tbl[] = { /* Gateway */ {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Gateway ", "LT31 ", "v1.3103 ", 0x55, 0x58, - {0x10, 0x0f, 0x00} }, - {"Gateway ", "LT31 ", "v1.3201 ", 0x55, 0x58, - {0x10, 0x0f, 0x00} }, - {"Gateway ", "LT31 ", "v1.3302 ", 0x55, 0x58, - {0x10, 0x0f, 0x00} }, + {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x10, 0x0f, 0x00} }, /* Packard Bell */ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, @@ -495,13 +492,26 @@ static struct platform_driver acerhdf_driver = { .remove = acerhdf_remove, }; +/* checks if str begins with start */ +static int str_starts_with(const char *str, const char *start) +{ + unsigned long str_len = 0, start_len = 0; + + str_len = strlen(str); + start_len = strlen(start); + + if (str_len >= start_len && + !strncmp(str, start, start_len)) + return 1; + + return 0; +} /* check hardware */ static int acerhdf_check_hardware(void) { char const *vendor, *version, *product; - int i; - unsigned long prod_len = 0; + const struct bios_settings_t *bt = NULL; /* get BIOS data */ vendor = dmi_get_system_info(DMI_SYS_VENDOR); @@ -523,20 +533,20 @@ static int acerhdf_check_hardware(void) kernelmode = 0; } - prod_len = strlen(product); - if (verbose) pr_info("BIOS info: %s %s, product: %s\n", vendor, version, product); /* search BIOS version and vendor in BIOS settings table */ - for (i = 0; bios_tbl[i].version[0]; i++) { - if (strlen(bios_tbl[i].product) >= prod_len && - !strncmp(bios_tbl[i].product, product, - strlen(bios_tbl[i].product)) && - !strcmp(bios_tbl[i].vendor, vendor) && - !strcmp(bios_tbl[i].version, version)) { - bios_cfg = &bios_tbl[i]; + for (bt = bios_tbl; bt->vendor[0]; bt++) { + /* + * check if actual hardware BIOS vendor, product and version + * IDs start with the strings of BIOS table entry + */ + if (str_starts_with(vendor, bt->vendor) && + str_starts_with(product, bt->product) && + str_starts_with(version, bt->version)) { + bios_cfg = bt; break; } } -- cgit v1.2.3 From 3e9b988e4edf065d39c1343937f717319b1c1065 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Fri, 4 Dec 2009 10:10:09 +0100 Subject: wmi: Free the allocated acpi objects through wmi_get_event_data These function allocate an acpi object by calling wmi_get_event_data, which then calls acpi_evaluate_object, and it is not freed afterwards. And kernel doc is fixed for parameters of wmi_get_event_data. Signed-off-by: Anisse Astier Acked-by: Randy Dunlap Acked-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 1 + drivers/platform/x86/hp-wmi.c | 2 ++ drivers/platform/x86/wmi.c | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 67f3fe71c50..6561dfc028e 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -238,6 +238,7 @@ static void dell_wmi_notify(u32 value, void *context) input_sync(dell_wmi_input_dev); } } + kfree(obj); } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 63c3e658a88..db10c5d007e 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -381,6 +381,8 @@ static void hp_wmi_notify(u32 value, void *context) } else printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", eventcode); + + kfree(obj); } static int __init hp_wmi_input_setup(void) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index e425a868cd3..9f93d6c0f51 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -540,8 +540,8 @@ EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); /** * wmi_get_event_data - Get WMI data associated with an event * - * @event - Event to find - * &out - Buffer to hold event data + * @event: Event to find + * @out: Buffer to hold event data. out->pointer should be freed with kfree() * * Returns extra data associated with an event in WMI. */ -- cgit v1.2.3 From 1fdd407f4e3f2ecb453954cbebb6c22491c61853 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 17 Dec 2009 22:19:42 -0800 Subject: dell-wmi: do not keep driver loaded on unsupported boxes There is no point in having the driver loaded in memory if we fail to locate particular WMI GUID. Signed-off-by: Dmitry Torokhov Acked-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 6561dfc028e..916ccb2b316 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -325,37 +325,34 @@ static int __init dell_wmi_init(void) int err; if (wmi_has_guid(DELL_EVENT_GUID)) { + printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); + return -ENODEV; + } - dmi_walk(find_hk_type, NULL); - - err = dell_wmi_input_setup(); - - if (err) - return err; - - err = wmi_install_notify_handler(DELL_EVENT_GUID, - dell_wmi_notify, NULL); - if (err) { - input_unregister_device(dell_wmi_input_dev); - printk(KERN_ERR "dell-wmi: Unable to register" - " notify handler - %d\n", err); - return err; - } + dmi_walk(find_hk_type, NULL); + acpi_video = acpi_video_backlight_support(); - acpi_video = acpi_video_backlight_support(); + err = dell_wmi_input_setup(); + if (err) + return err; - } else - printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); + err = wmi_install_notify_handler(DELL_EVENT_GUID, + dell_wmi_notify, NULL); + if (err) { + input_unregister_device(dell_wmi_input_dev); + printk(KERN_ERR + "dell-wmi: Unable to register notify handler - %d\n", + err); + return err; + } return 0; } static void __exit dell_wmi_exit(void) { - if (wmi_has_guid(DELL_EVENT_GUID)) { - wmi_remove_notify_handler(DELL_EVENT_GUID); - input_unregister_device(dell_wmi_input_dev); - } + wmi_remove_notify_handler(DELL_EVENT_GUID); + input_unregister_device(dell_wmi_input_dev); } module_init(dell_wmi_init); -- cgit v1.2.3 From 4d5f177caf1ef78f5e7eaee75b66b4d534445682 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 18 Dec 2009 15:29:22 +0100 Subject: acer-wmi, msi-wmi: Remove needless DMI MODULE_ALIAS Now that we have WMI autoloading the DMI matching is not needed anymore. Signed-off-by: Thomas Renninger Acked-by: Carlos Corbacho Acked-by: Anisse Astier Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 3 --- drivers/platform/x86/msi-wmi.c | 10 ---------- 2 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 454970d2d70..07d14dfdf0b 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -96,9 +96,6 @@ struct acer_quirks { MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"); -/* Temporary workaround until the WMI sysfs interface goes in */ -MODULE_ALIAS("dmi:*:*Acer*:*:"); - /* * Interface capability flags */ diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 0c8fe145c4a..7f77f908bb0 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -34,16 +34,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45"); MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"); -/* Temporary workaround until the WMI sysfs interface goes in - { "svn", DMI_SYS_VENDOR }, - { "pn", DMI_PRODUCT_NAME }, - { "pvr", DMI_PRODUCT_VERSION }, - { "rvn", DMI_BOARD_VENDOR }, - { "rn", DMI_BOARD_NAME }, -*/ - -MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*"); - #define DRV_NAME "msi-wmi" #define DRV_PFX DRV_NAME ": " -- cgit v1.2.3 From 154280fd0e890814a249bf4a79b4340fb367f1a7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Dec 2009 03:37:28 +0000 Subject: serial: sh-sci: earlyprintk zero uartclk fix This establishes a sensible max baud rate for the earlyprintk cases where the port's uartclk has not yet been determined. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 68c7f6cfd72..a8869905113 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -897,11 +897,21 @@ static void sci_shutdown(struct uart_port *port) static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - unsigned int status, baud, smr_val; + unsigned int status, baud, smr_val, max_baud; int t = -1; - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - if (likely(baud)) + /* + * earlyprintk comes here early on with port->uartclk set to zero. + * the clock framework is not up and running at this point so here + * we assume that 115200 is the maximum baud rate. please note that + * the baud rate is not programmed during earlyprintk - it is assumed + * that the previous boot loader has enabled required clocks and + * setup the baud rate generator hardware for us already. + */ + max_baud = port->uartclk ? port->uartclk / 16 : 115200; + + baud = uart_get_baud_rate(port, termios, old, 0, max_baud); + if (likely(baud && port->uartclk)) t = SCBRR_VALUE(baud, port->uartclk); do { -- cgit v1.2.3 From 32b53076c31ce9159740b744d5eb5d9505312add Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Dec 2009 14:52:43 +0900 Subject: serial: sh-sci: Convert tremaining ctrl_xxx I/O routines to __raw_xxx. ctrl_xxx() is an antiquated SH interface, while __raw_xxx is the standard API that accomplishes the same thing. As such, this converts the remaining sh-sci straggles over, which enables the driver to be wired up for ARM SH-Mobile CPUs as well. Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 4 +- drivers/serial/sh-sci.h | 118 ++++++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index a8869905113..37f0de9dd9c 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -222,9 +222,9 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) Set SCP6MD1,0 = {01} (output) */ __raw_writew((data & 0x0fcf) | 0x1000, SCPCR); - data = ctrl_inb(SCPDR); + data = __raw_readb(SCPDR); /* Set /RTS2 (bit6) = 0 */ - ctrl_outb(data & 0xbf, SCPDR); + __raw_writeb(data & 0xbf, SCPDR); } } #elif defined(CONFIG_CPU_SUBTYPE_SH7722) diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index a32094eeb42..0efcded59ae 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -517,20 +517,20 @@ static const struct __attribute__((packed)) { static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfffffe80) - return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCI */ + return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */ if (port->mapbase == 0xa4000150) - return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ + return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xa4000140) - return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ + return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7705) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == SCIF0) - return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ + return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ if (port->mapbase == SCIF2) - return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ + return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) @@ -557,68 +557,68 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */ + return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */ if (port->mapbase == 0xffe80000) - return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe80000) - return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7757) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfe4b0000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; if (port->mapbase == 0xfe4c0000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; if (port->mapbase == 0xfe4d0000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; } #elif defined(CONFIG_CPU_SUBTYPE_SH7760) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfe600000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfe610000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfe620000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7343) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe20000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe30000) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7366) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ + return __raw_readb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7722) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(PSDR) & 0x02 ? 1 : 0; /* SCIF0 */ + return __raw_readb(PSDR) & 0x02 ? 1 : 0; /* SCIF0 */ if (port->mapbase == 0xffe10000) - return ctrl_inb(PADR) & 0x40 ? 1 : 0; /* SCIF1 */ + return __raw_readb(PADR) & 0x40 ? 1 : 0; /* SCIF1 */ if (port->mapbase == 0xffe20000) - return ctrl_inb(PWDR) & 0x04 ? 1 : 0; /* SCIF2 */ + return __raw_readb(PWDR) & 0x04 ? 1 : 0; /* SCIF2 */ return 1; } @@ -626,17 +626,17 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */ + return __raw_readb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */ if (port->mapbase == 0xffe10000) - return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */ + return __raw_readb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */ if (port->mapbase == 0xffe20000) - return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */ + return __raw_readb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */ if (port->mapbase == 0xa4e30000) - return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */ + return __raw_readb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */ if (port->mapbase == 0xa4e40000) - return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */ + return __raw_readb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */ if (port->mapbase == 0xa4e50000) - return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ + return __raw_readb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7724) @@ -645,9 +645,9 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->type == PORT_SCIF) - return ctrl_inw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0; + return __raw_readw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0; if (port->type == PORT_SCIFA) - return ctrl_inw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0; + return __raw_readw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0; return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) @@ -665,11 +665,11 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe08000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */ return 1; } @@ -677,20 +677,20 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xff923000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xff924000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xff925000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7780) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ @@ -698,17 +698,17 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffea0000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffeb0000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffec0000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffed0000) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffee0000) - return ctrl_inw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffef0000) - return ctrl_inw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ @@ -718,22 +718,22 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfffe8000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe8800) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe9000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe9800) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ #if defined(CONFIG_CPU_SUBTYPE_SH7201) if (port->mapbase == 0xfffeA000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffeA800) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffeB000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffeB800) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ #endif return 1; } @@ -741,24 +741,24 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xf8400000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xf8410000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xf8420000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SHX3) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffc30000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffc40000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffc50000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffc60000) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #endif -- cgit v1.2.3 From 44ef00e6482e755f36629773abc2aee83a6f53e3 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 18 Dec 2009 15:29:23 +0100 Subject: hp-wmi: Fix two memleaks Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/platform/x86/hp-wmi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index db10c5d007e..8781d8fa7a5 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -134,10 +134,15 @@ static int hp_wmi_perform_query(int query, int write, int value) obj = output.pointer; - if (!obj || obj->type != ACPI_TYPE_BUFFER) + if (!obj) return -EINVAL; + else if (obj->type != ACPI_TYPE_BUFFER) { + kfree(obj); + return -EINVAL; + } bios_return = *((struct bios_return *)obj->buffer.pointer); + kfree(obj); if (bios_return.return_code > 0) return bios_return.return_code * -1; else @@ -340,10 +345,12 @@ static void hp_wmi_notify(u32 value, void *context) if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { printk(KERN_INFO "HP WMI: Unknown response received\n"); + kfree(obj); return; } eventcode = *((u8 *) obj->buffer.pointer); + kfree(obj); if (eventcode == 0x4) eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 0); -- cgit v1.2.3 From 529aa8cb0a59367d08883f818e8c47028e819d0d Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 21 Dec 2009 16:20:01 -0800 Subject: classmate-laptop: add support for Classmate PC ACPI devices This add supports for devices like keyboard, backlight, tablet and accelerometer. This work is supported by International Syst S/A. [randy.dunlap@oracle.com: cmpc_acpi: depends on ACPI] [akpm@linux-foundation.org: readability tweaks] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 12 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/classmate-laptop.c | 609 ++++++++++++++++++++++++++++++++ 3 files changed, 622 insertions(+) create mode 100644 drivers/platform/x86/classmate-laptop.c (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index fc5bf9d2a3f..ec4faffe6b0 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -464,4 +464,16 @@ config TOSHIBA_BT_RFKILL If you have a modern Toshiba laptop with a Bluetooth and an RFKill switch (such as the Portege R500), say Y. + +config ACPI_CMPC + tristate "CMPC Laptop Extras" + depends on X86 && ACPI + select INPUT + select BACKLIGHT_CLASS_DEVICE + default n + help + Support for Intel Classmate PC ACPI devices, including some + keys as input device, backlight device, tablet and accelerometer + devices. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index b7474b6a8bf..9cd9fa0a27e 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o +obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c new file mode 100644 index 00000000000..ed90082cdf1 --- /dev/null +++ b/drivers/platform/x86/classmate-laptop.c @@ -0,0 +1,609 @@ +/* + * Copyright (C) 2009 Thadeu Lima de Souza Cascardo + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + + +struct cmpc_accel { + int sensitivity; +}; + +#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 + + +/* + * Generic input device code. + */ + +typedef void (*input_device_init)(struct input_dev *dev); + +static int cmpc_add_acpi_notify_device(struct acpi_device *acpi, char *name, + input_device_init idev_init) +{ + struct input_dev *inputdev; + int error; + + inputdev = input_allocate_device(); + if (!inputdev) + return -ENOMEM; + inputdev->name = name; + inputdev->dev.parent = &acpi->dev; + idev_init(inputdev); + error = input_register_device(inputdev); + if (error) { + input_free_device(inputdev); + return error; + } + dev_set_drvdata(&acpi->dev, inputdev); + return 0; +} + +static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi) +{ + struct input_dev *inputdev = dev_get_drvdata(&acpi->dev); + input_unregister_device(inputdev); + return 0; +} + +/* + * Accelerometer code. + */ +static acpi_status cmpc_start_accel(acpi_handle handle) +{ + union acpi_object param[2]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x3; + param[1].type = ACPI_TYPE_INTEGER; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_stop_accel(acpi_handle handle) +{ + union acpi_object param[2]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x4; + param[1].type = ACPI_TYPE_INTEGER; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_accel_set_sensitivity(acpi_handle handle, int val) +{ + union acpi_object param[2]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x02; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + input.count = 2; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_get_accel(acpi_handle handle, + unsigned char *x, + unsigned char *y, + unsigned char *z) +{ + union acpi_object param[2]; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, 0 }; + unsigned char *locs; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x01; + param[1].type = ACPI_TYPE_INTEGER; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, &output); + if (ACPI_SUCCESS(status)) { + union acpi_object *obj; + obj = output.pointer; + locs = obj->buffer.pointer; + *x = locs[0]; + *y = locs[1]; + *z = locs[2]; + kfree(output.pointer); + } + return status; +} + +static void cmpc_accel_handler(struct acpi_device *dev, u32 event) +{ + if (event == 0x81) { + unsigned char x, y, z; + acpi_status status; + + status = cmpc_get_accel(dev->handle, &x, &y, &z); + if (ACPI_SUCCESS(status)) { + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + input_report_abs(inputdev, ABS_X, x); + input_report_abs(inputdev, ABS_Y, y); + input_report_abs(inputdev, ABS_Z, z); + input_sync(inputdev); + } + } +} + +static ssize_t cmpc_accel_sensitivity_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->sensitivity); +} + +static ssize_t cmpc_accel_sensitivity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long sensitivity; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = strict_strtoul(buf, 0, &sensitivity); + if (r) + return r; + + accel->sensitivity = sensitivity; + cmpc_accel_set_sensitivity(acpi->handle, sensitivity); + + return strnlen(buf, count); +} + +struct device_attribute cmpc_accel_sensitivity_attr = { + .attr = { .name = "sensitivity", .mode = 0660 }, + .show = cmpc_accel_sensitivity_show, + .store = cmpc_accel_sensitivity_store +}; + +static int cmpc_accel_open(struct input_dev *input) +{ + struct acpi_device *acpi; + + acpi = to_acpi_device(input->dev.parent); + if (ACPI_SUCCESS(cmpc_start_accel(acpi->handle))) + return 0; + return -EIO; +} + +static void cmpc_accel_close(struct input_dev *input) +{ + struct acpi_device *acpi; + + acpi = to_acpi_device(input->dev.parent); + cmpc_stop_accel(acpi->handle); +} + +static void cmpc_accel_idev_init(struct input_dev *inputdev) +{ + set_bit(EV_ABS, inputdev->evbit); + input_set_abs_params(inputdev, ABS_X, 0, 255, 8, 0); + input_set_abs_params(inputdev, ABS_Y, 0, 255, 8, 0); + input_set_abs_params(inputdev, ABS_Z, 0, 255, 8, 0); + inputdev->open = cmpc_accel_open; + inputdev->close = cmpc_accel_close; +} + +static int cmpc_accel_add(struct acpi_device *acpi) +{ + int error; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + accel = kmalloc(sizeof(*accel), GFP_KERNEL); + if (!accel) + return -ENOMEM; + + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; + cmpc_accel_set_sensitivity(acpi->handle, accel->sensitivity); + + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr); + if (error) + goto failed_file; + + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel", + cmpc_accel_idev_init); + if (error) + goto failed_input; + + inputdev = dev_get_drvdata(&acpi->dev); + dev_set_drvdata(&inputdev->dev, accel); + + return 0; + +failed_input: + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr); +failed_file: + kfree(accel); + return error; +} + +static int cmpc_accel_remove(struct acpi_device *acpi, int type) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr); + return cmpc_remove_acpi_notify_device(acpi); +} + +static const struct acpi_device_id cmpc_accel_device_ids[] = { + {"ACCE0000", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_accel_device_ids); + +static struct acpi_driver cmpc_accel_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc_accel", + .class = "cmpc_accel", + .ids = cmpc_accel_device_ids, + .ops = { + .add = cmpc_accel_add, + .remove = cmpc_accel_remove, + .notify = cmpc_accel_handler, + } +}; + + +/* + * Tablet mode code. + */ +static acpi_status cmpc_get_tablet(acpi_handle handle, + unsigned long long *value) +{ + union acpi_object param; + struct acpi_object_list input; + unsigned long long output; + acpi_status status; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0x01; + input.count = 1; + input.pointer = ¶m; + status = acpi_evaluate_integer(handle, "TCMD", &input, &output); + if (ACPI_SUCCESS(status)) + *value = output; + return status; +} + +static void cmpc_tablet_handler(struct acpi_device *dev, u32 event) +{ + unsigned long long val = 0; + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + if (event == 0x81) { + if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) + input_report_switch(inputdev, SW_TABLET_MODE, !val); + } +} + +static void cmpc_tablet_idev_init(struct input_dev *inputdev) +{ + unsigned long long val = 0; + struct acpi_device *acpi; + + set_bit(EV_SW, inputdev->evbit); + set_bit(SW_TABLET_MODE, inputdev->swbit); + + acpi = to_acpi_device(inputdev->dev.parent); + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) + input_report_switch(inputdev, SW_TABLET_MODE, !val); +} + +static int cmpc_tablet_add(struct acpi_device *acpi) +{ + return cmpc_add_acpi_notify_device(acpi, "cmpc_tablet", + cmpc_tablet_idev_init); +} + +static int cmpc_tablet_remove(struct acpi_device *acpi, int type) +{ + return cmpc_remove_acpi_notify_device(acpi); +} + +static int cmpc_tablet_resume(struct acpi_device *acpi) +{ + struct input_dev *inputdev = dev_get_drvdata(&acpi->dev); + unsigned long long val = 0; + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) + input_report_switch(inputdev, SW_TABLET_MODE, !val); + return 0; +} + +static const struct acpi_device_id cmpc_tablet_device_ids[] = { + {"TBLT0000", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_tablet_device_ids); + +static struct acpi_driver cmpc_tablet_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc_tablet", + .class = "cmpc_tablet", + .ids = cmpc_tablet_device_ids, + .ops = { + .add = cmpc_tablet_add, + .remove = cmpc_tablet_remove, + .resume = cmpc_tablet_resume, + .notify = cmpc_tablet_handler, + } +}; + + +/* + * Backlight code. + */ + +static acpi_status cmpc_get_brightness(acpi_handle handle, + unsigned long long *value) +{ + union acpi_object param; + struct acpi_object_list input; + unsigned long long output; + acpi_status status; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0xC0; + input.count = 1; + input.pointer = ¶m; + status = acpi_evaluate_integer(handle, "GRDI", &input, &output); + if (ACPI_SUCCESS(status)) + *value = output; + return status; +} + +static acpi_status cmpc_set_brightness(acpi_handle handle, + unsigned long long value) +{ + union acpi_object param[2]; + struct acpi_object_list input; + acpi_status status; + unsigned long long output; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0xC0; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = value; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_integer(handle, "GWRI", &input, &output); + return status; +} + +static int cmpc_bl_get_brightness(struct backlight_device *bd) +{ + acpi_status status; + acpi_handle handle; + unsigned long long brightness; + + handle = bl_get_data(bd); + status = cmpc_get_brightness(handle, &brightness); + if (ACPI_SUCCESS(status)) + return brightness; + else + return -1; +} + +static int cmpc_bl_update_status(struct backlight_device *bd) +{ + acpi_status status; + acpi_handle handle; + + handle = bl_get_data(bd); + status = cmpc_set_brightness(handle, bd->props.brightness); + if (ACPI_SUCCESS(status)) + return 0; + else + return -1; +} + +static struct backlight_ops cmpc_bl_ops = { + .get_brightness = cmpc_bl_get_brightness, + .update_status = cmpc_bl_update_status +}; + +static int cmpc_bl_add(struct acpi_device *acpi) +{ + struct backlight_device *bd; + + bd = backlight_device_register("cmpc_bl", &acpi->dev, + acpi->handle, &cmpc_bl_ops); + bd->props.max_brightness = 7; + dev_set_drvdata(&acpi->dev, bd); + return 0; +} + +static int cmpc_bl_remove(struct acpi_device *acpi, int type) +{ + struct backlight_device *bd; + + bd = dev_get_drvdata(&acpi->dev); + backlight_device_unregister(bd); + return 0; +} + +static const struct acpi_device_id cmpc_device_ids[] = { + {"IPML200", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_device_ids); + +static struct acpi_driver cmpc_bl_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc", + .class = "cmpc", + .ids = cmpc_device_ids, + .ops = { + .add = cmpc_bl_add, + .remove = cmpc_bl_remove + } +}; + + +/* + * Extra keys code. + */ +static int cmpc_keys_codes[] = { + KEY_UNKNOWN, + KEY_WLAN, + KEY_SWITCHVIDEOMODE, + KEY_BRIGHTNESSDOWN, + KEY_BRIGHTNESSUP, + KEY_VENDOR, + KEY_MAX +}; + +static void cmpc_keys_handler(struct acpi_device *dev, u32 event) +{ + struct input_dev *inputdev; + int code = KEY_MAX; + + if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes)) + code = cmpc_keys_codes[event & 0x0F]; + inputdev = dev_get_drvdata(&dev->dev);; + input_report_key(inputdev, code, !(event & 0x10)); +} + +static void cmpc_keys_idev_init(struct input_dev *inputdev) +{ + int i; + + set_bit(EV_KEY, inputdev->evbit); + for (i = 0; cmpc_keys_codes[i] != KEY_MAX; i++) + set_bit(cmpc_keys_codes[i], inputdev->keybit); +} + +static int cmpc_keys_add(struct acpi_device *acpi) +{ + return cmpc_add_acpi_notify_device(acpi, "cmpc_keys", + cmpc_keys_idev_init); +} + +static int cmpc_keys_remove(struct acpi_device *acpi, int type) +{ + return cmpc_remove_acpi_notify_device(acpi); +} + +static const struct acpi_device_id cmpc_keys_device_ids[] = { + {"FnBT0000", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_keys_device_ids); + +static struct acpi_driver cmpc_keys_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc_keys", + .class = "cmpc_keys", + .ids = cmpc_keys_device_ids, + .ops = { + .add = cmpc_keys_add, + .remove = cmpc_keys_remove, + .notify = cmpc_keys_handler, + } +}; + + +/* + * General init/exit code. + */ + +static int cmpc_init(void) +{ + int r; + + r = acpi_bus_register_driver(&cmpc_keys_acpi_driver); + if (r) + goto failed_keys; + + r = acpi_bus_register_driver(&cmpc_bl_acpi_driver); + if (r) + goto failed_bl; + + r = acpi_bus_register_driver(&cmpc_tablet_acpi_driver); + if (r) + goto failed_tablet; + + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver); + if (r) + goto failed_accel; + + return r; + +failed_accel: + acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); + +failed_tablet: + acpi_bus_unregister_driver(&cmpc_bl_acpi_driver); + +failed_bl: + acpi_bus_unregister_driver(&cmpc_keys_acpi_driver); + +failed_keys: + return r; +} + +static void cmpc_exit(void) +{ + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); + acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); + acpi_bus_unregister_driver(&cmpc_bl_acpi_driver); + acpi_bus_unregister_driver(&cmpc_keys_acpi_driver); +} + +module_init(cmpc_init); +module_exit(cmpc_exit); -- cgit v1.2.3 From 603adaf6b3e37450235f0ddb5986b961b3146a79 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 14:52:53 +0100 Subject: amd64_edac: fix K8 chip select reporting Fix the case when amd64_debug_display_dimm_sizes() reports only half the amount of DRAM on it because it doesn't account for when the single DCT operates in 128-bit mode and merges chip selects from different DIMMs. Reported-by: Johannes Hirte LKML-Reference: <200912112202.48173.johannes.hirte@fem.tu-ilmenau.de> Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index df5b68433f3..784cc5a1ebc 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1700,11 +1700,14 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, */ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) { - int dimm, size0, size1; + int dimm, size0, size1, factor = 0; u32 dbam; u32 *dcsb; if (boot_cpu_data.x86 == 0xf) { + if (pvt->dclr0 & F10_WIDTH_128) + factor = 1; + /* K8 families < revF not supported yet */ if (pvt->ext_model < K8_REV_F) return; @@ -1732,7 +1735,8 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n", - dimm * 2, size0, dimm * 2 + 1, size1); + dimm * 2, size0 << factor, + dimm * 2 + 1, size1 << factor); } } -- cgit v1.2.3 From 8f68ed9728193b1f2fb53ba06031b06bd8b3d1b4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 15:15:59 +0100 Subject: amd64_edac: fix driver instance freeing Fix use-after-free errors by pushing all memory-freeing calls to the end of amd64_remove_one_instance(). Reported-by: Darren Jenkins LKML-Reference: <1261370306.11354.52.camel@ICE-BOX> Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 784cc5a1ebc..fb0d36b4741 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2929,16 +2929,15 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) amd64_free_mc_sibling_devices(pvt); - kfree(pvt); - mci->pvt_info = NULL; - - mci_lookup[pvt->mc_node_id] = NULL; - /* unregister from EDAC MCE */ amd_report_gart_errors(false); amd_unregister_ecc_decoder(amd64_decode_bus_error); /* Free the EDAC CORE resources */ + mci->pvt_info = NULL; + mci_lookup[pvt->mc_node_id] = NULL; + + kfree(pvt); edac_mc_free(mci); } -- cgit v1.2.3 From 56b34b91e22313294154cee0c16e294cf8a45b61 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 18:13:01 +0100 Subject: amd64_edac: make driver loading more robust Currently, the module does not initialize fully when the DIMMs aren't ECC but remains still loaded. Propagate the error when no instance of the driver is properly initialized and prevent further loading. Reorganize and polish error handling in amd64_edac_init() while at it. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index fb0d36b4741..a8af27a7482 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3014,25 +3014,29 @@ static void amd64_setup_pci_device(void) static int __init amd64_edac_init(void) { int nb, err = -ENODEV; + bool load_ok = false; edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); opstate_init(); if (cache_k8_northbridges() < 0) - return err; + goto err_ret; msrs = msrs_alloc(); + if (!msrs) + goto err_ret; err = pci_register_driver(&amd64_pci_driver); if (err) - return err; + goto err_pci; /* * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd * amd64_pvt structs. These will be used in the 2nd stage init function * to finish initialization of the MC instances. */ + err = -ENODEV; for (nb = 0; nb < num_k8_northbridges; nb++) { if (!pvt_lookup[nb]) continue; @@ -3040,16 +3044,21 @@ static int __init amd64_edac_init(void) err = amd64_init_2nd_stage(pvt_lookup[nb]); if (err) goto err_2nd_stage; - } - amd64_setup_pci_device(); + load_ok = true; + } - return 0; + if (load_ok) { + amd64_setup_pci_device(); + return 0; + } err_2nd_stage: - debugf0("2nd stage failed\n"); pci_unregister_driver(&amd64_pci_driver); - +err_pci: + msrs_free(msrs); + msrs = NULL; +err_ret: return err; } -- cgit v1.2.3 From 43f5e68733cfe8bed3c30b5c14c4993dffb29766 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 18:55:18 +0100 Subject: amd64_edac: fix forcing module load/unload Clear the override flag after force-loading the module. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index a8af27a7482..63c04d31cd7 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2690,9 +2690,8 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) amd64_printk(KERN_WARNING, "%s", ecc_warning); return -ENODEV; } - } else - /* CLEAR the override, since BIOS controlled it */ ecc_enable_override = 0; + } return 0; } -- cgit v1.2.3 From 92389102b6832fc779f5c37f1d9e3eaadea6e059 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 19:21:41 +0100 Subject: amd64_edac: restrict PCI config space access Do not access F2x19[0,4] on K8 since they're undefined there. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 63c04d31cd7..c5facd951dd 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2349,7 +2349,7 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); - if (!dct_ganging_enabled(pvt)) { + if (!dct_ganging_enabled(pvt) && boot_cpu_data.x86 >= 0x10) { amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); } -- cgit v1.2.3 From 5213c32f9d56db6a5e3ae8d2977a3961e98211fd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 19:11:12 +0100 Subject: edac, pci: remove pesky debug printk Do not spam the logs needlessly with the sole info that edac_pci_dev_parity_clear is being called. Signed-off-by: Borislav Petkov --- drivers/edac/edac_pci_sysfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 422728cfe99..fb60a877d76 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -534,8 +534,6 @@ static void edac_pci_dev_parity_clear(struct pci_dev *dev) { u8 header_type; - debugf0("%s()\n", __func__); - get_pci_parity_status(dev, 0); /* read the device TYPE, looking for bridges */ -- cgit v1.2.3 From ed5a35acbb48d512332a53565e6341c65eecfa29 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 24 Dec 2009 13:36:21 +0000 Subject: VIDEO: cyberpro: pci_request_regions needs a persistent name Don't pass a name pointer from the kernel stack, it will not survive and will result in corrupted /proc/iomem output. Signed-off-by: Russell King --- drivers/video/cyber2000fb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index da7c01b39be..3a561df2e8a 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1573,15 +1573,15 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (err) return err; - err = pci_request_regions(dev, name); - if (err) - return err; - err = -ENOMEM; cfb = cyberpro_alloc_fb_info(id->driver_data, name); if (!cfb) goto failed_release; + err = pci_request_regions(dev, cfb->fb.fix.id); + if (err) + goto failed_regions; + cfb->dev = dev; cfb->region = pci_ioremap_bar(dev, 0); if (!cfb->region) @@ -1633,10 +1633,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) failed: iounmap(cfb->region); failed_ioremap: + pci_release_regions(dev); +failed_regions: cyberpro_free_fb_info(cfb); failed_release: - pci_release_regions(dev); - return err; } -- cgit v1.2.3 From a62e8f1978f49e52f87a711ff6711b323d4b12ff Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 24 Dec 2009 11:34:16 +0300 Subject: ACPI: EC: Accelerate query execution Split EC query handling into acknowledge and execution phase. This allows much smaller pending query lattency and lowers chances of EC going "wild" and losing events. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14858 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 122 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fd1801bdee6..9cc38857c33 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -201,14 +201,13 @@ unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } -static void acpi_ec_gpe_query(void *ec_cxt); +static int acpi_ec_sync_query(struct acpi_ec *ec); -static int ec_check_sci(struct acpi_ec *ec, u8 state) +static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_os_execute(OSL_EC_BURST_HANDLER, - acpi_ec_gpe_query, ec); + return acpi_ec_sync_query(ec); } return 0; } @@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, { unsigned long tmp; int ret = 0; - pr_debug(PREFIX "transaction start\n"); - /* disable GPE during transaction if storm is detected */ - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - acpi_disable_gpe(NULL, ec->gpe); - } if (EC_FLAGS_MSI) udelay(ACPI_EC_MSI_UDELAY); /* start transaction */ @@ -269,16 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - /* check if we received SCI during transaction */ - ec_check_sci(ec, acpi_ec_read_status(ec)); - /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_info(PREFIX "GPE storm detected, " - "transactions will use polling mode\n"); - set_bit(EC_FLAGS_GPE_STORM, &ec->flags); - } return ret; } @@ -321,7 +305,24 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } + pr_debug(PREFIX "transaction start\n"); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + acpi_disable_gpe(NULL, ec->gpe); + } + status = acpi_ec_transaction_unlocked(ec, t); + + /* check if we received SCI during transaction */ + ec_check_sci_sync(ec, acpi_ec_read_status(ec)); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe); + } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -443,7 +444,7 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); -static int acpi_ec_query(struct acpi_ec *ec, u8 * data) +static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) { int result; u8 d; @@ -452,20 +453,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; - /* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ - - result = acpi_ec_transaction(ec, &t); + result = acpi_ec_transaction_unlocked(ec, &t); if (result) return result; - if (!d) return -ENODATA; - *data = d; return 0; } @@ -509,43 +506,78 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -static void acpi_ec_gpe_query(void *ec_cxt) +static void acpi_ec_run(void *cxt) { - struct acpi_ec *ec = ec_cxt; - u8 value = 0; - struct acpi_ec_query_handler *handler, copy; - - if (!ec || acpi_ec_query(ec, &value)) + struct acpi_ec_query_handler *handler = cxt; + if (!handler) return; - mutex_lock(&ec->lock); + pr_debug(PREFIX "start query execution\n"); + if (handler->func) + handler->func(handler->data); + else if (handler->handle) + acpi_evaluate_object(handler->handle, NULL, NULL, NULL); + pr_debug(PREFIX "stop query execution\n"); + kfree(handler); +} + +static int acpi_ec_sync_query(struct acpi_ec *ec) +{ + u8 value = 0; + int status; + struct acpi_ec_query_handler *handler, *copy; + if ((status = acpi_ec_query_unlocked(ec, &value))) + return status; list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ - memcpy(©, handler, sizeof(copy)); - mutex_unlock(&ec->lock); - if (copy.func) { - copy.func(copy.data); - } else if (copy.handle) { - acpi_evaluate_object(copy.handle, NULL, NULL, NULL); - } - return; + copy = kmalloc(sizeof(*handler), GFP_KERNEL); + if (!copy) + return -ENOMEM; + memcpy(copy, handler, sizeof(*copy)); + pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); + return acpi_os_execute(OSL_GPE_HANDLER, + acpi_ec_run, copy); } } + return 0; +} + +static void acpi_ec_gpe_query(void *ec_cxt) +{ + struct acpi_ec *ec = ec_cxt; + if (!ec) + return; + mutex_lock(&ec->lock); + acpi_ec_sync_query(ec); mutex_unlock(&ec->lock); } +static void acpi_ec_gpe_query(void *ec_cxt); + +static int ec_check_sci(struct acpi_ec *ec, u8 state) +{ + if (state & ACPI_EC_FLAG_SCI) { + if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { + pr_debug(PREFIX "push gpe query to the queue\n"); + return acpi_os_execute(OSL_NOTIFY_HANDLER, + acpi_ec_gpe_query, ec); + } + } + return 0; +} + static u32 acpi_ec_gpe_handler(void *data) { struct acpi_ec *ec = data; - u8 status; pr_debug(PREFIX "~~~> interrupt\n"); - status = acpi_ec_read_status(ec); - advance_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) + advance_transaction(ec, acpi_ec_read_status(ec)); + if (ec_transaction_done(ec) && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { wake_up(&ec->wait); - ec_check_sci(ec, status); + ec_check_sci(ec, acpi_ec_read_status(ec)); + } return ACPI_INTERRUPT_HANDLED; } -- cgit v1.2.3 From 4a299bf591bc5bef3bde8316e603b9eaec5a7696 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 21:40:24 -0800 Subject: Input: speed up suspend/shutdown for PS/2 mice and keyboards Instead of doing full-blown reset while suspending or shutting down the box use lighter form of reset that should take less time. Tested-by: Alan Stern Tested-by: Rafael J. Wysocki Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 5 +++-- drivers/input/mouse/psmouse-base.c | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index a3573570c52..1f5e2ce327d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -134,7 +134,8 @@ static const unsigned short atkbd_unxlate_table[128] = { #define ATKBD_CMD_GETID 0x02f2 #define ATKBD_CMD_SETREP 0x10f3 #define ATKBD_CMD_ENABLE 0x00f4 -#define ATKBD_CMD_RESET_DIS 0x00f5 +#define ATKBD_CMD_RESET_DIS 0x00f5 /* Reset to defaults and disable */ +#define ATKBD_CMD_RESET_DEF 0x00f6 /* Reset to defaults */ #define ATKBD_CMD_SETALL_MBR 0x00fa #define ATKBD_CMD_RESET_BAT 0x02ff #define ATKBD_CMD_RESEND 0x00fe @@ -836,7 +837,7 @@ static void atkbd_cleanup(struct serio *serio) struct atkbd *atkbd = serio_get_drvdata(serio); atkbd_disable(atkbd); - ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT); + ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF); } diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index fd0bc094616..401ac6b6edd 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1137,7 +1137,10 @@ static void psmouse_cleanup(struct serio *serio) if (psmouse->cleanup) psmouse->cleanup(psmouse); - psmouse_reset(psmouse); +/* + * Reset the mouse to defaults (bare PS/2 protocol). + */ + ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); /* * Some boxes, such as HP nx7400, get terribly confused if mouse -- cgit v1.2.3 From ea486e681188d64c6a101d8d06414aef0f9f0cd3 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 21:40:43 -0800 Subject: Input: serio - do not mark kseriod freezable anymore We used to make kseriod freezable to prevent unnecessary attempts at resuming keyboard and mouse before taking hibernation image when suspend and hibernation were sharing PM operations. Now that they are separated and we don't risk resuming during 'thaw' we don't need to freeze kseriod anymore. This will allow us to start resetting mouse and keyboard a bit earlier, before rest of the userspace comes back up. Acked-by: Rafael J. Wysocki Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 0236f0d5fd9..e0f30186d51 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -284,13 +284,7 @@ static void serio_handle_event(void) mutex_lock(&serio_mutex); - /* - * Note that we handle only one event here to give swsusp - * a chance to freeze kseriod thread. Serio events should - * be pretty rare so we are not concerned about taking - * performance hit. - */ - if ((event = serio_get_event())) { + while ((event = serio_get_event())) { switch (event->type) { case SERIO_REGISTER_PORT: @@ -380,10 +374,9 @@ static struct serio *serio_get_pending_child(struct serio *parent) static int serio_thread(void *nothing) { - set_freezable(); do { serio_handle_event(); - wait_event_freezable(serio_wait, + wait_event_interruptible(serio_wait, kthread_should_stop() || !list_empty(&serio_event_list)); } while (!kthread_should_stop()); -- cgit v1.2.3 From 25ae08317647c68ed9276f7bdc07d0d5fd042628 Mon Sep 17 00:00:00 2001 From: Jari Vanhala Date: Thu, 24 Dec 2009 21:52:19 -0800 Subject: Input: ff-memless - start playing FF effects immediately Instead of waiting for the next timer tick to start playing an effect do it immediately. This mostly helps systems using low HZ setting. Signed-off-by: Jari Vanhala Acked-by: Anssi Hannula Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index b483b2995fa..decc51f45bf 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -411,8 +411,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) msecs_to_jiffies(state->effect->replay.length); state->adj_at = state->play_at; - ml_schedule_timer(ml); - } else { debug("initiated stop"); @@ -420,10 +418,10 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) __set_bit(FF_EFFECT_ABORTING, &state->flags); else __clear_bit(FF_EFFECT_STARTED, &state->flags); - - ml_play_effects(ml); } + ml_play_effects(ml); + return 0; } -- cgit v1.2.3 From 1b11c88d3e8f55dc9d193d19de11e3f7abc1b7d7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 21:44:19 -0800 Subject: Input: ff-memless - another fix for signed to unsigned overflow The commit 9e68177ef93b2f34eee5a1e1707bceef4b9ba69c changed 'gain' from signed to unsigned to fix an issue with rumble effect calculation, however it introduced problems when calculating constant effects. Having 'gain' being unsigned int was an unfortunate choice since it dominates all implicit type conversions causing everything to be treated as unsigned int. Let's change it back to signed int and simply add proper casts to rumble effect calculations. Reported-by: Gary Stein Acked-by: Anssi Hannula Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index decc51f45bf..9667a5fd6bd 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -225,7 +225,7 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) */ static void ml_combine_effects(struct ff_effect *effect, struct ml_effect_state *state, - unsigned int gain) + int gain) { struct ff_effect *new = state->effect; unsigned int strong, weak, i; @@ -252,8 +252,8 @@ static void ml_combine_effects(struct ff_effect *effect, break; case FF_RUMBLE: - strong = new->u.rumble.strong_magnitude * gain / 0xffff; - weak = new->u.rumble.weak_magnitude * gain / 0xffff; + strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; + weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; effect->u.rumble.strong_magnitude = min(strong + effect->u.rumble.strong_magnitude, 0xffffU); -- cgit v1.2.3 From 94ec26c855bc675259e4f1658673f458040affd7 Mon Sep 17 00:00:00 2001 From: Jari Vanhala Date: Thu, 24 Dec 2009 21:52:20 -0800 Subject: Input: ff-memless - add notion of direction to for rumble effects This adds simple direction calculation when combining effects. It's useful to decide motor direction for rumble (vibrator). Signed-off-by: Jari Vanhala Acked-by: Anssi Hannula Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 9667a5fd6bd..f967008f332 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -220,6 +220,22 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) return 0; } +/* + * Only left/right direction should be used (under/over 0x8000) for + * forward/reverse motor direction (to keep calculation fast & simple). + */ +static u16 ml_calculate_direction(u16 direction, u16 force, + u16 new_direction, u16 new_force) +{ + if (!force) + return new_direction; + if (!new_force) + return direction; + return (((u32)(direction >> 1) * force + + (new_direction >> 1) * new_force) / + (force + new_force)) << 1; +} + /* * Combine two effects and apply gain. */ @@ -254,6 +270,19 @@ static void ml_combine_effects(struct ff_effect *effect, case FF_RUMBLE: strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; + + if (effect->u.rumble.strong_magnitude + strong) + effect->direction = ml_calculate_direction( + effect->direction, + effect->u.rumble.strong_magnitude, + new->direction, strong); + else if (effect->u.rumble.weak_magnitude + weak) + effect->direction = ml_calculate_direction( + effect->direction, + effect->u.rumble.weak_magnitude, + new->direction, weak); + else + effect->direction = 0; effect->u.rumble.strong_magnitude = min(strong + effect->u.rumble.strong_magnitude, 0xffffU); @@ -268,6 +297,13 @@ static void ml_combine_effects(struct ff_effect *effect, /* here we also scale it 0x7fff => 0xffff */ i = i * gain / 0x7fff; + if (effect->u.rumble.strong_magnitude + i) + effect->direction = ml_calculate_direction( + effect->direction, + effect->u.rumble.strong_magnitude, + new->direction, i); + else + effect->direction = 0; effect->u.rumble.strong_magnitude = min(i + effect->u.rumble.strong_magnitude, 0xffffU); effect->u.rumble.weak_magnitude = -- cgit v1.2.3 From 98b7fb0472f828536a7786df6bd517322c0c17dc Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 22:37:49 -0800 Subject: Input: iforce - fix oops on device disconnect Do not try to free iforce device when we closing input device; disconnect is the only place where it should be deleted. Reported-by: Johannes Ebke Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 26 +++++--------------------- drivers/input/joystick/iforce/iforce-usb.c | 28 +++++++--------------------- drivers/input/joystick/iforce/iforce.h | 2 -- 3 files changed, 12 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index f6c688cae33..acc3a9efb00 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -210,7 +210,7 @@ static int iforce_open(struct input_dev *dev) return 0; } -static void iforce_release(struct input_dev *dev) +static void iforce_close(struct input_dev *dev) { struct iforce *iforce = input_get_drvdata(dev); int i; @@ -230,28 +230,12 @@ static void iforce_release(struct input_dev *dev) iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); } - switch (iforce->bus) { -#ifdef CONFIG_JOYSTICK_IFORCE_USB - case IFORCE_USB: - usb_kill_urb(iforce->irq); - - /* The device was unplugged before the file - * was released */ - if (iforce->usbdev == NULL) { - iforce_delete_device(iforce); - kfree(iforce); - } - break; -#endif - } -} - -void iforce_delete_device(struct iforce *iforce) -{ switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB case IFORCE_USB: - iforce_usb_delete(iforce); + usb_kill_urb(iforce->irq); + usb_kill_urb(iforce->out); + usb_kill_urb(iforce->ctrl); break; #endif #ifdef CONFIG_JOYSTICK_IFORCE_232 @@ -303,7 +287,7 @@ int iforce_init_device(struct iforce *iforce) input_dev->name = "Unknown I-Force device"; input_dev->open = iforce_open; - input_dev->close = iforce_release; + input_dev->close = iforce_close; /* * On-device memory allocation. diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 9f289d8f52c..c0ad8836944 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -186,33 +186,19 @@ fail: return err; } -/* Called by iforce_delete() */ -void iforce_usb_delete(struct iforce* iforce) -{ - usb_kill_urb(iforce->irq); - usb_kill_urb(iforce->out); - usb_kill_urb(iforce->ctrl); - - usb_free_urb(iforce->irq); - usb_free_urb(iforce->out); - usb_free_urb(iforce->ctrl); -} - static void iforce_usb_disconnect(struct usb_interface *intf) { struct iforce *iforce = usb_get_intfdata(intf); - int open = 0; /* FIXME! iforce->dev.handle->open; */ usb_set_intfdata(intf, NULL); - if (iforce) { - iforce->usbdev = NULL; - input_unregister_device(iforce->dev); - if (!open) { - iforce_delete_device(iforce); - kfree(iforce); - } - } + input_unregister_device(iforce->dev); + + usb_free_urb(iforce->irq); + usb_free_urb(iforce->out); + usb_free_urb(iforce->ctrl); + + kfree(iforce); } static struct usb_device_id iforce_usb_ids [] = { diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index f2d91f4028c..9f494b75848 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -150,11 +150,9 @@ void iforce_serial_xmit(struct iforce *iforce); /* iforce-usb.c */ void iforce_usb_xmit(struct iforce *iforce); -void iforce_usb_delete(struct iforce *iforce); /* iforce-main.c */ int iforce_init_device(struct iforce *iforce); -void iforce_delete_device(struct iforce *iforce); /* iforce-packets.c */ int iforce_control_playback(struct iforce*, u16 id, unsigned int); -- cgit v1.2.3 From dd219234d201431d0fc56a74e3a4a97ca3eb4589 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 24 Dec 2009 22:50:23 -0800 Subject: Input: matrix-keypad - handle cases when GPIOs can't be wakeup sources On certain boards not all GPIOs may be used as wakeup sources, in which case some of enable_irq_wake() calls will fail. On resume calling disable_irq_wake() will warn about unbalanced IRQ wake disable. Solve this by checking whether enable_irq_wake() succeeded or not and no not call disable_irq_wake() for these GPIOs/IRQs that have not been enabled. Reported-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/matrix_keypad.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 34f4a29d497..d3c8b61a941 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -29,11 +29,13 @@ struct matrix_keypad { unsigned short *keycodes; unsigned int row_shift; + DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS); + uint32_t last_key_state[MATRIX_MAX_COLS]; struct delayed_work work; + spinlock_t lock; bool scan_pending; bool stopped; - spinlock_t lock; }; /* @@ -222,9 +224,16 @@ static int matrix_keypad_suspend(struct device *dev) matrix_keypad_stop(keypad->input_dev); - if (device_may_wakeup(&pdev->dev)) - for (i = 0; i < pdata->num_row_gpios; i++) - enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + if (device_may_wakeup(&pdev->dev)) { + for (i = 0; i < pdata->num_row_gpios; i++) { + if (!test_bit(i, keypad->disabled_gpios)) { + unsigned int gpio = pdata->row_gpios[i]; + + if (enable_irq_wake(gpio_to_irq(gpio)) == 0) + __set_bit(i, keypad->disabled_gpios); + } + } + } return 0; } @@ -236,9 +245,15 @@ static int matrix_keypad_resume(struct device *dev) const struct matrix_keypad_platform_data *pdata = keypad->pdata; int i; - if (device_may_wakeup(&pdev->dev)) - for (i = 0; i < pdata->num_row_gpios; i++) - disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); + if (device_may_wakeup(&pdev->dev)) { + for (i = 0; i < pdata->num_row_gpios; i++) { + if (test_and_clear_bit(i, keypad->disabled_gpios)) { + unsigned int gpio = pdata->row_gpios[i]; + + disable_irq_wake(gpio_to_irq(gpio)); + } + } + } matrix_keypad_start(keypad->input_dev); -- cgit v1.2.3 From ead510cebcdf41c92fce2a909f342255b028a33d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Dec 2009 22:52:13 -0200 Subject: thinkpad-acpi: don't take the first ALSA slot by default We don't want to be the first soundcard. We don't want to shift other soundcards out of the way either, even if they load much later. Ask ALSA to (by default) load us in one of the last three slots. This can be overriden at will using the "index" parameter. Reported-by: Whoopie Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 448c8aeb166..3311b002056 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6388,7 +6388,7 @@ static struct ibm_struct brightness_driver_data = { #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME -static int alsa_index = SNDRV_DEFAULT_IDX1; +static int alsa_index = ~((1 << (SNDRV_CARDS - 3)) - 1); /* last three slots */ static char *alsa_id = "ThinkPadEC"; static int alsa_enable = SNDRV_DEFAULT_ENABLE1; -- cgit v1.2.3 From 74c75c1848b618f6717c1be887ad539ffac2e96d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Dec 2009 22:52:14 -0200 Subject: thinkpad-acpi: don't fail to load the entire module due to ALSA problems If we cannot create the ALSA mixer, it is a good reason to fail to load the volume subdriver, and not to fail to load the entire module. While at it, add more debugging messages, as the error paths are being used a lot more than I'd expect, and it is failing to set up the ALSA mixer on a number of ThinkPads. Reported-by: Peter Jordan Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 3311b002056..9b7da9c96e7 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6705,10 +6705,11 @@ static int __init volume_create_alsa_mixer(void) rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE, sizeof(struct tpacpi_alsa_data), &card); - if (rc < 0) - return rc; - if (!card) - return -ENOMEM; + if (rc < 0 || !card) { + printk(TPACPI_ERR + "Failed to create ALSA card structures: %d\n", rc); + return 1; + } BUG_ON(!card->private_data); data = card->private_data; @@ -6741,8 +6742,9 @@ static int __init volume_create_alsa_mixer(void) rc = snd_ctl_add(card, ctl_vol); if (rc < 0) { printk(TPACPI_ERR - "Failed to create ALSA volume control\n"); - goto err_out; + "Failed to create ALSA volume control: %d\n", + rc); + goto err_exit; } data->ctl_vol_id = &ctl_vol->id; } @@ -6750,22 +6752,25 @@ static int __init volume_create_alsa_mixer(void) ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL); rc = snd_ctl_add(card, ctl_mute); if (rc < 0) { - printk(TPACPI_ERR "Failed to create ALSA mute control\n"); - goto err_out; + printk(TPACPI_ERR "Failed to create ALSA mute control: %d\n", + rc); + goto err_exit; } data->ctl_mute_id = &ctl_mute->id; snd_card_set_dev(card, &tpacpi_pdev->dev); rc = snd_card_register(card); - -err_out: if (rc < 0) { - snd_card_free(card); - card = NULL; + printk(TPACPI_ERR "Failed to register ALSA card: %d\n", rc); + goto err_exit; } alsa_card = card; - return rc; + return 0; + +err_exit: + snd_card_free(card); + return 1; } #define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */ -- cgit v1.2.3 From ff850c339a1a6a7724537160c73cdc09a483fc5d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Dec 2009 22:52:15 -0200 Subject: thinkpad-acpi: make volume subdriver optional Allow the user to choose through Kconfig if the Console Audio Control interface (aka "volume subdriver") should be available or not. This not only saves some memory, but also allows the thinkpad-acpi driver to be built-in even if ALSA is modular when the console audio control interface is not wanted. This change fixes a build problem that is causing some annoyances, in a way that doesn't disable the entire driver on kernels without ALSA support. Signed-off-by: Henrique de Moraes Holschuh Cc: Ingo Molnar Cc: Amerigo Wang Cc: Helight Xu Cc: Takashi Iwai Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 23 +++++++++++++++++++++++ drivers/platform/x86/thinkpad_acpi.c | 26 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index ec4faffe6b0..2462dc30b39 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -233,6 +233,29 @@ config THINKPAD_ACPI If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. +config THINKPAD_ACPI_ALSA_SUPPORT + bool "Console audio control ALSA interface" + depends on THINKPAD_ACPI + depends on SND + depends on SND = y || THINKPAD_ACPI = SND + default y + ---help--- + Enables monitoring of the built-in console audio output control + (headphone and speakers), which is operated by the mute and (in + some ThinkPad models) volume hotkeys. + + If this option is enabled, ThinkPad-ACPI will export an ALSA card + with a single read-only mixer control, which should be used for + on-screen-display feedback purposes by the Desktop Environment. + + Optionally, the driver will also allow software control (the + ALSA mixer will be made read-write). Please refer to the driver + documentation for details. + + All IBM models have both volume and mute control. Newer Lenovo + models only have mute control (the volume hotkeys are just normal + keys and volume control is done through the main HDA mixer). + config THINKPAD_ACPI_DEBUGFACILITIES bool "Maintainer debug facilities" depends on THINKPAD_ACPI diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 9b7da9c96e7..e67e4feb35c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -6384,6 +6384,8 @@ static struct ibm_struct brightness_driver_data = { * and we leave them unchanged. */ +#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT + #define TPACPI_ALSA_DRVNAME "ThinkPad EC" #define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control" #define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME @@ -7021,6 +7023,28 @@ static struct ibm_struct volume_driver_data = { .shutdown = volume_shutdown, }; +#else /* !CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ + +#define alsa_card NULL + +static void inline volume_alsa_notify_change(void) +{ +} + +static int __init volume_init(struct ibm_init_struct *iibm) +{ + printk(TPACPI_INFO + "volume: disabled as there is no ALSA support in this kernel\n"); + + return 1; +} + +static struct ibm_struct volume_driver_data = { + .name = "volume", +}; + +#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ + /************************************************************************* * Fan subdriver */ @@ -8743,6 +8767,7 @@ MODULE_PARM_DESC(hotkey_report_mode, "used for backwards compatibility with userspace, " "see documentation"); +#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT module_param_named(volume_mode, volume_mode, uint, 0444); MODULE_PARM_DESC(volume_mode, "Selects volume control strategy: " @@ -8765,6 +8790,7 @@ module_param_named(id, alsa_id, charp, 0444); MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer"); module_param_named(enable, alsa_enable, bool, 0444); MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer"); +#endif /* CONFIG_THINKPAD_ACPI_ALSA_SUPPORT */ #define TPACPI_PARAM(feature) \ module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ -- cgit v1.2.3 From 6e5b08ee941af38cfc6456158e7e04c1bc49306f Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Dec 2009 22:52:17 -0200 Subject: thinkpad-acpi: improve Kconfig help text Document that rfkill and ALSA functionality exists, but requires the subsystems to be available, and not modular if thinkpad-acpi is not modular. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 2462dc30b39..db32c25e360 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -231,6 +231,11 @@ config THINKPAD_ACPI This driver was formerly known as ibm-acpi. + Extra functionality will be available if the rfkill (CONFIG_RFKILL) + and/or ALSA (CONFIG_SND) subsystems are available in the kernel. + Note that if you want ThinkPad-ACPI to be built-in instead of + modular, ALSA and rfkill will also have to be built-in. + If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. config THINKPAD_ACPI_ALSA_SUPPORT -- cgit v1.2.3 From da2c3f0ead336c04b4d1ad36ff42d8d264f44f65 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Sat, 26 Dec 2009 16:25:18 +0800 Subject: [ARM] pxafb: fix building issue of incorrect reference Commit "d2a34c1 drivers/video: Move dereference after NULL test" introduced a build error of "fbi->dev->platform_data->smart_update" being unknown type to the compiler, fix this by removing the unnecessary test of 'fbi'. Cc: Julia Lawall Signed-off-by: Eric Miao --- drivers/video/pxafb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 415858b421b..825b665245b 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1221,9 +1221,9 @@ static void setup_smart_timing(struct pxafb_info *fbi, static int pxafb_smart_thread(void *arg) { struct pxafb_info *fbi = arg; - struct pxafb_mach_info *inf; + struct pxafb_mach_info *inf = fbi->dev->platform_data; - if (!fbi || !fbi->dev->platform_data->smart_update) { + if (!inf->smart_update) { pr_err("%s: not properly initialized, thread terminated\n", __func__); return -EINVAL; -- cgit v1.2.3 From 0798219f6154baa6a8efe767bfffb4a724e4b1e1 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 28 Dec 2009 16:58:38 +0100 Subject: drbd: Use drbd_crypto_is_hash() instead of an open coded check Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_nl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 4e0726aa53b..3313901a486 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1271,7 +1271,7 @@ static int drbd_nl_net_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, goto fail; } - if (crypto_tfm_alg_type(crypto_hash_tfm(tfm)) != CRYPTO_ALG_TYPE_SHASH) { + if (!drbd_crypto_is_hash(crypto_hash_tfm(tfm))) { retcode = ERR_AUTH_ALG_ND; goto fail; } -- cgit v1.2.3 From 0a6dbf2bc4ea3781c530f895e2d92fd3c4a735a2 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Mon, 28 Dec 2009 16:58:38 +0100 Subject: drbd: Fix for a race between IO and a detach operation [Bugz 262] In D_DISKLESS we do not hand out any new references to ldev (local_cnt) therefore waiting until all previously handed out refereces got returned is sufficient before actually freeing mdev->ldev. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 9348f33f624..e898ad9eb1c 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1298,6 +1298,7 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os, dev_err(DEV, "Sending state in drbd_io_error() failed\n"); } + wait_event(mdev->misc_wait, !atomic_read(&mdev->local_cnt)); lc_destroy(mdev->resync); mdev->resync = NULL; lc_destroy(mdev->act_log); -- cgit v1.2.3 From 89f01d5cd3c7ef01239bf15283181a0091c78657 Mon Sep 17 00:00:00 2001 From: Johannes Thoma Date: Tue, 29 Dec 2009 16:38:04 +0100 Subject: drbd: Kconfig fix !CONFIG_OPT evalues to FALSE if CONFIG_OPT='m'. Do not display the "DRBD disabled..." message if the dependencies are compiled as module. Signed-off-by: Johannes Thoma Signed-off-by: Philipp Reisner --- drivers/block/drbd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/Kconfig b/drivers/block/drbd/Kconfig index f4acd04ebee..df098378739 100644 --- a/drivers/block/drbd/Kconfig +++ b/drivers/block/drbd/Kconfig @@ -3,7 +3,7 @@ # comment "DRBD disabled because PROC_FS, INET or CONNECTOR not selected" - depends on !PROC_FS || !INET || !CONNECTOR + depends on PROC_FS='n' || INET='n' || CONNECTOR='n' config BLK_DEV_DRBD tristate "DRBD Distributed Replicated Block Device support" -- cgit v1.2.3 From db5d247ae811f49185a71e703b65acad845e4b18 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Thu, 24 Dec 2009 12:05:58 +0100 Subject: firewire: fix use of multiple AV/C devices, allow multiple FCP listeners Control of more than one AV/C device at once --- e.g. camcorders, tape decks, audio devices, TV tuners --- failed or worked only unreliably, depending on driver implementation. This affected kernelspace and userspace drivers alike and was caused by firewire-core's inability to accept multiple registrations of FCP listeners. The fix allows multiple address handlers to be registered for the FCP command and response registers. When a request for these registers is received, all handlers are invoked, and the Firewire response is generated by the core and not by any handler. The cdev API does not change, i.e., userspace is still expected to send a response for FCP requests; this response is silently ignored. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter (changelog, rebased, whitespace) --- drivers/firewire/core-cdev.c | 26 ++++--- drivers/firewire/core-transaction.c | 118 ++++++++++++++++++++++++++------ drivers/media/dvb/firewire/firedtv-fw.c | 12 +--- 3 files changed, 114 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 231e6ee5ba4..2cb22d160f6 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -601,8 +601,9 @@ static void release_request(struct client *client, struct inbound_transaction_resource *r = container_of(resource, struct inbound_transaction_resource, resource); - fw_send_response(client->device->card, r->request, - RCODE_CONFLICT_ERROR); + if (r->request) + fw_send_response(client->device->card, r->request, + RCODE_CONFLICT_ERROR); kfree(r); } @@ -645,7 +646,8 @@ static void handle_request(struct fw_card *card, struct fw_request *request, failed: kfree(r); kfree(e); - fw_send_response(card, request, RCODE_CONFLICT_ERROR); + if (request) + fw_send_response(card, request, RCODE_CONFLICT_ERROR); } static void release_address_handler(struct client *client, @@ -715,15 +717,17 @@ static int ioctl_send_response(struct client *client, void *buffer) r = container_of(resource, struct inbound_transaction_resource, resource); - if (request->length < r->length) - r->length = request->length; - - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { - ret = -EFAULT; - goto out; + if (r->request) { + if (request->length < r->length) + r->length = request->length; + if (copy_from_user(r->data, u64_to_uptr(request->data), + r->length)) { + ret = -EFAULT; + goto out; + } + fw_send_response(client->device->card, r->request, + request->rcode); } - - fw_send_response(client->device->card, r->request, request->rcode); out: kfree(r); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 842739df23e..495849eb13c 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -432,14 +432,20 @@ static struct fw_address_handler *lookup_overlapping_address_handler( return NULL; } +static bool is_enclosing_handler(struct fw_address_handler *handler, + unsigned long long offset, size_t length) +{ + return handler->offset <= offset && + offset + length <= handler->offset + handler->length; +} + static struct fw_address_handler *lookup_enclosing_address_handler( struct list_head *list, unsigned long long offset, size_t length) { struct fw_address_handler *handler; list_for_each_entry(handler, list, link) { - if (handler->offset <= offset && - offset + length <= handler->offset + handler->length) + if (is_enclosing_handler(handler, offset, length)) return handler; } @@ -465,6 +471,12 @@ const struct fw_address_region fw_unit_space_region = { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, }; #endif /* 0 */ +static bool is_in_fcp_region(u64 offset, size_t length) +{ + return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && + offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END); +} + /** * fw_core_add_address_handler - register for incoming requests * @handler: callback @@ -477,8 +489,11 @@ const struct fw_address_region fw_unit_space_region = * give the details of the particular request. * * Return value: 0 on success, non-zero otherwise. + * * The start offset of the handler's address region is determined by * fw_core_add_address_handler() and is returned in handler->offset. + * + * Address allocations are exclusive, except for the FCP registers. */ int fw_core_add_address_handler(struct fw_address_handler *handler, const struct fw_address_region *region) @@ -498,10 +513,12 @@ int fw_core_add_address_handler(struct fw_address_handler *handler, handler->offset = region->start; while (handler->offset + handler->length <= region->end) { - other = - lookup_overlapping_address_handler(&address_handler_list, - handler->offset, - handler->length); + if (is_in_fcp_region(handler->offset, handler->length)) + other = NULL; + else + other = lookup_overlapping_address_handler + (&address_handler_list, + handler->offset, handler->length); if (other != NULL) { handler->offset += other->length; } else { @@ -668,6 +685,9 @@ static struct fw_request *allocate_request(struct fw_packet *p) void fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) { + if (WARN_ONCE(!request, "invalid for FCP address handlers")) + return; + /* unified transaction or broadcast transaction: don't respond */ if (request->ack != ACK_PENDING || HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) { @@ -686,26 +706,15 @@ void fw_send_response(struct fw_card *card, } EXPORT_SYMBOL(fw_send_response); -void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) +static void handle_exclusive_region_request(struct fw_card *card, + struct fw_packet *p, + struct fw_request *request, + unsigned long long offset) { struct fw_address_handler *handler; - struct fw_request *request; - unsigned long long offset; unsigned long flags; int tcode, destination, source; - if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) - return; - - request = allocate_request(p); - if (request == NULL) { - /* FIXME: send statically allocated busy packet. */ - return; - } - - offset = - ((unsigned long long) - HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2]; tcode = HEADER_GET_TCODE(p->header[0]); destination = HEADER_GET_DESTINATION(p->header[0]); source = HEADER_GET_SOURCE(p->header[1]); @@ -732,6 +741,73 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) request->data, request->length, handler->callback_data); } + +static void handle_fcp_region_request(struct fw_card *card, + struct fw_packet *p, + struct fw_request *request, + unsigned long long offset) +{ + struct fw_address_handler *handler; + unsigned long flags; + int tcode, destination, source; + + if ((offset != (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && + offset != (CSR_REGISTER_BASE | CSR_FCP_RESPONSE)) || + request->length > 0x200) { + fw_send_response(card, request, RCODE_ADDRESS_ERROR); + + return; + } + + tcode = HEADER_GET_TCODE(p->header[0]); + destination = HEADER_GET_DESTINATION(p->header[0]); + source = HEADER_GET_SOURCE(p->header[1]); + + if (tcode != TCODE_WRITE_QUADLET_REQUEST && + tcode != TCODE_WRITE_BLOCK_REQUEST) { + fw_send_response(card, request, RCODE_TYPE_ERROR); + + return; + } + + spin_lock_irqsave(&address_handler_lock, flags); + list_for_each_entry(handler, &address_handler_list, link) { + if (is_enclosing_handler(handler, offset, request->length)) + handler->address_callback(card, NULL, tcode, + destination, source, + p->generation, p->speed, + offset, request->data, + request->length, + handler->callback_data); + } + spin_unlock_irqrestore(&address_handler_lock, flags); + + fw_send_response(card, request, RCODE_COMPLETE); +} + +void fw_core_handle_request(struct fw_card *card, struct fw_packet *p) +{ + struct fw_request *request; + unsigned long long offset; + + if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE) + return; + + request = allocate_request(p); + if (request == NULL) { + /* FIXME: send statically allocated busy packet. */ + return; + } + + offset = ((u64)HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | + p->header[2]; + + if (!is_in_fcp_region(offset, request->length)) + handle_exclusive_region_request(card, p, request, offset); + else + handle_fcp_region_request(card, p, request, offset); + +} EXPORT_SYMBOL(fw_core_handle_request); void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index fe44789ab03..6223bf01efe 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -202,14 +202,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request, unsigned long flags; int su; - if ((tcode != TCODE_WRITE_QUADLET_REQUEST && - tcode != TCODE_WRITE_BLOCK_REQUEST) || - offset != CSR_REGISTER_BASE + CSR_FCP_RESPONSE || - length == 0 || - (((u8 *)payload)[0] & 0xf0) != 0) { - fw_send_response(card, request, RCODE_TYPE_ERROR); + if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0) return; - } su = ((u8 *)payload)[1] & 0x7; @@ -230,10 +224,8 @@ static void handle_fcp(struct fw_card *card, struct fw_request *request, } spin_unlock_irqrestore(&node_list_lock, flags); - if (fdtv) { + if (fdtv) avc_recv(fdtv, payload, length); - fw_send_response(card, request, RCODE_COMPLETE); - } } static struct fw_address_handler fcp_handler = { -- cgit v1.2.3 From cf0e575dcc4cab9fd955e9bec49df7e8ee30a7cf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 26 Dec 2009 01:34:29 +0100 Subject: firewire: cdev: fix another memory leak in an error path If copy_from_user in an FW_CDEV_IOC_SEND_RESPONSE ioctl failed, the fw_request pointed to by the inbound_transaction_resource is no longer referenced and needs to be freed. Signed-off-by: Stefan Richter --- drivers/firewire/core-cdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2cb22d160f6..e6d63849e78 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -723,6 +723,7 @@ static int ioctl_send_response(struct client *client, void *buffer) if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { ret = -EFAULT; + kfree(r->request); goto out; } fw_send_response(client->device->card, r->request, -- cgit v1.2.3 From 090699c0530ae5380a9b8511d76f656cc437bb6e Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 26 Dec 2009 01:35:14 +0100 Subject: firewire: ohci: always use packet-per-buffer mode for isochronous reception This is a minimal change meant for the short term: Never set the ohci->use_dualbuffer flag to true. There are two reasons to do so: - Packet-per-buffer mode and dual-buffer mode do not behave the same under certain circumstances, notably if several packets are covered by a single fw_cdev_iso_packet descriptor. http://marc.info/?l=linux1394-devel&m=124965653718313 Therefore the driver stack should not silently choose one or the other mode but should leave the choice to the high-level driver (regardless if kernel driver or userspace driver). Or simply always only offer packet-per-buffer mode, since a considerable number of controllers, even current ones, does not offer dual-buffer support. - Even under circumstances where packet-per-buffer mode and dual-buffer mode behave exactly the same --- notably when used through libraw1394, libdc1394, as well as the current two kernel drivers which use isochronous reception (firewire-net and firedtv) --- we are still faced with the problem that several OHCI 1.1 controllers have bugs in dual-buffer mode. Although it looks like we have identified most of those buggy controllers by now, we cannot be quite sure about that. So, use packet-per-buffer by default from now on. This change should be followed up by a more complete solution: Either extend the in-kernel API and the userspace ABI by a choice between the two IR modes or remove all dual-buffer related code from firewire-ohci. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 96768e16086..a61571c63c5 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2226,7 +2226,6 @@ static int ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, if (rest == 0) return -EINVAL; - /* FIXME: make packet-per-buffer/dual-buffer a context option */ while (rest > 0) { d = context_get_descriptors(&ctx->context, z + header_z, &d_bus); @@ -2470,7 +2469,10 @@ static int __devinit pci_probe(struct pci_dev *dev, } version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; +#if 0 + /* FIXME: make it a context option or remove dual-buffer mode */ ohci->use_dualbuffer = version >= OHCI_VERSION_1_1; +#endif /* dual-buffer mode is broken if more than one IR context is active */ if (dev->vendor == PCI_VENDOR_ID_AGERE && -- cgit v1.2.3 From 5d7db0499e5bb13381a7fbfdd0d913b966545e75 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 26 Dec 2009 01:36:53 +0100 Subject: firewire, ieee1394: update Kconfig help Update the Kconfig help texts of both stacks to encourage a general move from the older to the newer drivers. However, do not label ieee1394 as "Obsolete" yet, as the newer drivers have not been deployed as default stack in the majority of Linux distributions yet, and those who start doing so now may still want to install the old drivers as fallback for unforeseen issues. Since Linux 2.6.32, FireWire audio devices can be driven by the newer firewire driver stack too, hence remove an outdated comment about audio devices. Also remove comments about library versions since the 2nd generation of libraw1394 and libdc1394 is now in common use; details on library versions can be read at the wiki link from the help texts. Signed-off-by: Stefan Richter --- drivers/Kconfig | 2 +- drivers/firewire/Kconfig | 44 +++++++++++------------------------- drivers/ieee1394/Kconfig | 59 ++++++++++++++++++++++++++++++++++-------------- 3 files changed, 56 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 8a07363417e..368ae6d3a09 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -28,7 +28,7 @@ source "drivers/md/Kconfig" source "drivers/message/fusion/Kconfig" -source "drivers/ieee1394/Kconfig" +source "drivers/firewire/Kconfig" source "drivers/message/i2o/Kconfig" diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index 13efcd36207..a9371b36a9b 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -1,5 +1,10 @@ +menu "IEEE 1394 (FireWire) support" + depends on PCI || BROKEN + # firewire-core does not depend on PCI but is + # not useful without PCI controller driver + comment "You can enable one or both FireWire driver stacks." -comment "See the help texts for more information." +comment "The newer stack is recommended." config FIREWIRE tristate "FireWire driver stack" @@ -15,16 +20,6 @@ config FIREWIRE To compile this driver as a module, say M here: the module will be called firewire-core. - This module functionally replaces ieee1394, raw1394, and video1394. - To access it from application programs, you generally need at least - libraw1394 v2. IIDC/DCAM applications need libdc1394 v2. - No libraries are required to access storage devices through the - firewire-sbp2 driver. - - NOTE: - FireWire audio devices currently require the old drivers (ieee1394, - ohci1394, raw1394). - config FIREWIRE_OHCI tristate "OHCI-1394 controllers" depends on PCI && FIREWIRE @@ -34,22 +29,7 @@ config FIREWIRE_OHCI is the only chipset in use, so say Y here. To compile this driver as a module, say M here: The module will be - called firewire-ohci. It replaces ohci1394 of the classic IEEE 1394 - stack. - - NOTE: - If you want to install firewire-ohci and ohci1394 together, you - should configure them only as modules and blacklist the driver(s) - which you don't want to have auto-loaded. Add either - - blacklist firewire-ohci - or - blacklist ohci1394 - blacklist video1394 - blacklist dv1394 - - to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf - depending on your distribution. + called firewire-ohci. config FIREWIRE_OHCI_DEBUG bool @@ -66,8 +46,7 @@ config FIREWIRE_SBP2 like scanners. To compile this driver as a module, say M here: The module will be - called firewire-sbp2. It replaces sbp2 of the classic IEEE 1394 - stack. + called firewire-sbp2. You should also enable support for disks, CD-ROMs, etc. in the SCSI configuration section. @@ -83,5 +62,8 @@ config FIREWIRE_NET NOTE, this driver is not stable yet! To compile this driver as a module, say M here: The module will be - called firewire-net. It replaces eth1394 of the classic IEEE 1394 - stack. + called firewire-net. + +source "drivers/ieee1394/Kconfig" + +endmenu diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index f102fcc7e52..e02096cf7d9 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -1,8 +1,3 @@ -menu "IEEE 1394 (FireWire) support" - depends on PCI || BROKEN - -source "drivers/firewire/Kconfig" - config IEEE1394 tristate "Legacy alternative FireWire driver stack" depends on PCI || BROKEN @@ -16,8 +11,13 @@ config IEEE1394 is the core support only, you will also need to select a driver for your IEEE 1394 adapter. - To compile this driver as a module, say M here: the - module will be called ieee1394. + To compile this driver as a module, say M here: the module will be + called ieee1394. + + NOTE: + ieee1394 is superseded by the newer firewire-core driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. config IEEE1394_OHCI1394 tristate "OHCI-1394 controllers" @@ -29,19 +29,23 @@ config IEEE1394_OHCI1394 use one of these chipsets. It should work with any OHCI-1394 compliant card, however. - To compile this driver as a module, say M here: the - module will be called ohci1394. + To compile this driver as a module, say M here: the module will be + called ohci1394. NOTE: + ohci1394 is superseded by the newer firewire-ohci driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + If you want to install firewire-ohci and ohci1394 together, you should configure them only as modules and blacklist the driver(s) which you don't want to have auto-loaded. Add either - blacklist firewire-ohci - or blacklist ohci1394 blacklist video1394 blacklist dv1394 + or + blacklist firewire-ohci to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf depending on your distribution. @@ -58,8 +62,8 @@ config IEEE1394_PCILYNX Instruments PCILynx chip. Note: this driver is written for revision 2 of this chip and may not work with revision 0. - To compile this driver as a module, say M here: the - module will be called pcilynx. + To compile this driver as a module, say M here: the module will be + called pcilynx. Only some old and now very rare PCI and CardBus cards and PowerMacs G3 B&W contain the PCILynx controller. Therefore @@ -79,6 +83,14 @@ config IEEE1394_SBP2 You should also enable support for disks, CD-ROMs, etc. in the SCSI configuration section. + To compile this driver as a module, say M here: the module will be + called sbp2. + + NOTE: + sbp2 is superseded by the newer firewire-sbp2 driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_SBP2_PHYS_DMA bool "Enable replacement for physical DMA in SBP2" depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL @@ -111,6 +123,11 @@ config IEEE1394_ETH1394 The module is called eth1394 although it does not emulate Ethernet. + NOTE: + eth1394 is superseded by the newer firewire-net driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_RAWIO tristate "raw1394 userspace interface" depends on IEEE1394 @@ -123,6 +140,11 @@ config IEEE1394_RAWIO To compile this driver as a module, say M here: the module will be called raw1394. + NOTE: + raw1394 is superseded by the newer firewire-core driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_VIDEO1394 tristate "video1394 userspace interface" depends on IEEE1394 && IEEE1394_OHCI1394 @@ -136,13 +158,18 @@ config IEEE1394_VIDEO1394 To compile this driver as a module, say M here: the module will be called video1394. + NOTE: + video1394 is superseded by the newer firewire-core driver. See + http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for + further information on how to switch to the new FireWire drivers. + config IEEE1394_DV1394 tristate "dv1394 userspace interface (deprecated)" depends on IEEE1394 && IEEE1394_OHCI1394 help The dv1394 driver is unsupported and may be removed from Linux in a - future release. Its functionality is now provided by raw1394 together - with libraries such as libiec61883. + future release. Its functionality is now provided by either + raw1394 or firewire-core together with libraries such as libiec61883. config IEEE1394_VERBOSEDEBUG bool "Excessive debugging output" @@ -153,5 +180,3 @@ config IEEE1394_VERBOSEDEBUG will quickly result in large amounts of data sent to the system log. Say Y if you really need the debugging output. Everyone else says N. - -endmenu -- cgit v1.2.3 From cbd1998377504df005302ac90d49db72a48552a6 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 30 Dec 2009 12:08:49 +1100 Subject: md: Fix unfortunate interaction with evms evms configures md arrays by: open device send ioctl close device for each different ioctl needed. Since 2.6.29, the device can disappear after the 'close' unless a significant configuration has happened to the device. The change made by "SET_ARRAY_INFO" can too minor to stop the device from disappearing, but important enough that losing the change is bad. So: make sure SET_ARRAY_INFO sets mddev->ctime, and keep the device active as long as ctime is non-zero (it gets zeroed with lots of other things when the array is stopped). This is suitable for -stable kernels since 2.6.29. Signed-off-by: NeilBrown Cc: stable@kernel.org --- drivers/md/md.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index f4f5f82f9f5..7862231a075 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -386,7 +386,9 @@ static void mddev_put(mddev_t *mddev) if (!atomic_dec_and_lock(&mddev->active, &all_mddevs_lock)) return; if (!mddev->raid_disks && list_empty(&mddev->disks) && - !mddev->hold_active) { + mddev->ctime == 0 && !mddev->hold_active) { + /* Array is not configured at all, and not held active, + * so destroy it */ list_del(&mddev->all_mddevs); if (mddev->gendisk) { /* we did a probe so need to clean up. @@ -5262,6 +5264,10 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) mddev->minor_version = info->minor_version; mddev->patch_version = info->patch_version; mddev->persistent = !info->not_persistent; + /* ensure mddev_put doesn't delete this now that there + * is some minimal configuration. + */ + mddev->ctime = get_seconds(); return 0; } mddev->major_version = MD_MAJOR_VERSION; -- cgit v1.2.3 From 0f9552b5dc4fe10da37fa3f4a4ca185d90fa41c9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 30 Dec 2009 12:08:50 +1100 Subject: md: fix small irregularity with start_ro module parameter The start_ro modules parameter can be used to force arrays to be started in 'auto-readonly' in which they are read-only until the first write. This ensures that no resync/recovery happens until something else writes to the device. This is important for resume-from-disk off an md array. However if an array is started 'readonly' (by writing 'readonly' to the 'array_state' sysfs attribute) we want it to be really 'readonly', not 'auto-readonly'. So strengthen the condition to only set auto-readonly if the array is not already read-only. Signed-off-by: NeilBrown --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 7862231a075..d2aff720907 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4357,7 +4357,7 @@ static int do_md_run(mddev_t * mddev) mddev->barriers_work = 1; mddev->ok_start_degraded = start_dirty_degraded; - if (start_readonly) + if (start_readonly && mddev->ro == 0) mddev->ro = 2; /* read-only, but switch on first write */ err = mddev->pers->run(mddev); -- cgit v1.2.3 From a2d79c324ac0c26ae9995a312a7731067a7f01fc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 21 Dec 2009 18:18:36 -0700 Subject: md: make recovery started by do_md_run() visible via sync_action By default md_do_sync() will perform recovery if no other actions are specified. However, action_show() relies on MD_RECOVERY_RECOVER to be set otherwise it returns 'idle'. So, add a missing set MD_RECOVERY_RECOVER when starting recovery. Signed-off-by: Dan Williams Signed-off-by: NeilBrown --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index d2aff720907..fd55f2a555b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4436,6 +4436,7 @@ static int do_md_run(mddev_t * mddev) if (spares && mddev->pers->sync_request) { mddev->recovery = 0; set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); mddev->sync_thread = md_register_thread(md_do_sync, mddev, "resync"); -- cgit v1.2.3 From 7fb9dadc91948ddd16d1d32e414b5e71ec63b97b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 30 Dec 2009 15:19:08 +1100 Subject: md: remove unnecessary code from do_md_run Since commit dfc7064500061677720fa26352963c772d3ebe6b, ->hot_remove_disks has not removed non-failed devices from an array until recovery is no longer possible. So the code in do_md_run to get around the fact that md_check_recovery (which calls ->hot_remove_disks) would remove partially-in-sync devices is no longer needed. So remove it. Signed-off-by: NeilBrown --- drivers/md/md.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index fd55f2a555b..c4bdf060175 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4421,34 +4421,6 @@ static int do_md_run(mddev_t * mddev) set_capacity(disk, mddev->array_sectors); - /* If there is a partially-recovered drive we need to - * start recovery here. If we leave it to md_check_recovery, - * it will remove the drives and not do the right thing - */ - if (mddev->degraded && !mddev->sync_thread) { - int spares = 0; - list_for_each_entry(rdev, &mddev->disks, same_set) - if (rdev->raid_disk >= 0 && - !test_bit(In_sync, &rdev->flags) && - !test_bit(Faulty, &rdev->flags)) - /* complete an interrupted recovery */ - spares++; - if (spares && mddev->pers->sync_request) { - mddev->recovery = 0; - set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); - mddev->sync_thread = md_register_thread(md_do_sync, - mddev, - "resync"); - if (!mddev->sync_thread) { - printk(KERN_ERR "%s: could not start resync" - " thread...\n", - mdname(mddev)); - /* leave the spares where they are, it shouldn't hurt */ - mddev->recovery = 0; - } - } - } md_wakeup_thread(mddev->thread); md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ -- cgit v1.2.3 From 404e4b43fdd6daa7b4a9f81bc7e4358281d763fa Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 30 Dec 2009 15:25:23 +1100 Subject: md: allow a resync that is waiting for other resync to complete, to be aborted. If two arrays share a device, then they will not both resync at the same time. One will wait for the other to complete. While waiting, the MD_RECOVERY_INTR flag is not checked so a device failure, which would make the resync pointless, does not cause the resync to abort, so the failed device cannot be removed (as it cannot be remove while a resync is happening). So add a test for MD_RECOVERY_INTR. Reported-by: Brett Russ Signed-off-by: NeilBrown --- drivers/md/md.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index c4bdf060175..dd3dfe42d5a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -6473,10 +6473,11 @@ void md_do_sync(mddev_t *mddev) mddev->curr_resync = 2; try_again: - if (kthread_should_stop()) { + if (kthread_should_stop()) set_bit(MD_RECOVERY_INTR, &mddev->recovery); + + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) goto skip; - } for_each_mddev(mddev2, tmp) { if (mddev2 == mddev) continue; -- cgit v1.2.3 From 27d0567ab635bc2af11be48f91c8d5a7a2dca2e4 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 17 Dec 2009 08:50:25 +0100 Subject: ACPI: fix ACPI=n allmodconfig build Today's -tip failed to build because commit 9e368fa011d4e0aa050db348d69514900520e40b ("ipmi: add PNP discovery (ACPI namespace via PNPACPI)") from today's upstream kernel causes the following build failure on x86, for CONFIG_ACPI=n && CONFIG_IPMI_SI=y: drivers/char/ipmi/ipmi_si_intf.c:3208: error: 'ipmi_pnp_driver' undeclared (first use in this function) drivers/char/ipmi/ipmi_si_intf.c:3208: error: (Each undeclared identifier is reported only once drivers/char/ipmi/ipmi_si_intf.c:3208: error: for each function it appears in.) drivers/char/ipmi/ipmi_si_intf.c:3334: error: 'ipmi_pnp_driver' undeclared (first use in this function) The reason is that the ipmi_pnp_driver depends on ACPI facilities and is only made available under ACPI - while the registration and unregistration is made dependent on CONFIG_PNP: #ifdef CONFIG_PNP pnp_register_driver(&ipmi_pnp_driver); #endif The solution is to only register this driver under ACPI. (Also, the CONFIG_PNP dependency is not needed because pnp_register_driver() is stubbed out in the !CONFIG_PNP case.) Signed-off-by: Ingo Molnar Acked-by: Myron Stowe Signed-off-by: Len Brown --- drivers/char/ipmi/ipmi_si_intf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 679cd08b80b..176f1751237 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -3204,7 +3204,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_ACPI spmi_find_bmc(); #endif -#ifdef CONFIG_PNP +#ifdef CONFIG_ACPI pnp_register_driver(&ipmi_pnp_driver); #endif @@ -3330,7 +3330,7 @@ static __exit void cleanup_ipmi_si(void) #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif -#ifdef CONFIG_PNP +#ifdef CONFIG_ACPI pnp_unregister_driver(&ipmi_pnp_driver); #endif -- cgit v1.2.3 From 28c32e99bdf5ab838e7179c1aaca5a35a07f2a2b Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 13 Jul 2009 10:33:24 +0800 Subject: ACPI video: no warning message if "acpi_backlight=vendor" is used AML code always sends notifications to ACPI video device, even if we disable the ACPI backlight control by using boot option "acpi_backlight=vendor". In this case we should not print any warning message. http://bugzilla.kernel.org/show_bug.cgi?id=13671#c14 Sigend-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591..3b063a6ac52 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1979,6 +1979,10 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) unsigned long long level_current, level_next; int result = -EINVAL; + /* no warning message if acpi_backlight=vendor is used */ + if (!acpi_video_backlight_support()) + return 0; + if (!device->brightness) goto out; -- cgit v1.2.3 From e01ce79b7f6ebc5b57128ee058811aa8f9059319 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 29 Jul 2009 08:53:29 +0800 Subject: ACPI video: correct error-handling code backlight_device_register may return an ERR_PTR value rather than a valid pointer. Problem found by Julia Lawall, properly fixed by Zhang Rui. Signed-off-by: Zhang Rui Acked-by: Julia Lawall Signed-off-by: Len Brown --- drivers/acpi/video.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591..3f685db1a76 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -999,8 +999,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) sprintf(name, "acpi_video%d", count++); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - device->backlight->props.max_brightness = device->brightness->count-3; kfree(name); + if (IS_ERR(device->backlight)) + return; + device->backlight->props.max_brightness = device->brightness->count-3; result = sysfs_create_link(&device->backlight->dev.kobj, &device->dev->dev.kobj, "device"); -- cgit v1.2.3 From c6bde2d9cb75a41cd2b331953784843b4caa89df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Bolldorf?= Date: Tue, 29 Dec 2009 23:06:52 -0800 Subject: Input: psmouse - fix compile warning in hgpk module The variable 'dev' is unused in function 'hgpk_register'. Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/hgpk.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index b146237266d..90be30e9355 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -427,7 +427,6 @@ static void hgpk_recalib_work(struct work_struct *work) static int hgpk_register(struct psmouse *psmouse) { - struct input_dev *dev = psmouse->dev; int err; /* register handlers */ -- cgit v1.2.3 From e97006ae1c87f9630b6f5c4d4384921059d881a8 Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Tue, 29 Dec 2009 23:19:31 -0800 Subject: Input: wistron - fix test for CONFIG_PM This should fix the following compile warning: drivers/input/misc/wistron_btns.c:1331:5: warning: "CONFIG_PM" is not defined Signed-off-by: Rakib Mullick Signed-off-by: Dmitry Torokhov --- drivers/input/misc/wistron_btns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 38da6ab0438..c0afb71a3a6 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -1328,7 +1328,7 @@ static struct platform_driver wistron_driver = { .driver = { .name = "wistron-bios", .owner = THIS_MODULE, -#if CONFIG_PM +#ifdef CONFIG_PM .pm = &wistron_pm_ops, #endif }, -- cgit v1.2.3 From 614af4eeb9e89806c001dab50c59e11f40753601 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 29 Dec 2009 23:19:31 -0800 Subject: Input: lifebook - add CONFIG_DMI dependency Lifebook protocol can only be activated if we find known DMI signature. It is useles without DMI. Reported-by: Rakib Mullick Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/Kconfig | 2 +- drivers/input/mouse/lifebook.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 3feeb3af8ab..c714ca2407f 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS config MOUSE_PS2_LIFEBOOK bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED default y - depends on MOUSE_PS2 && X86 + depends on MOUSE_PS2 && X86 && DMI help Say Y here if you have a Fujitsu B-series Lifebook PS/2 TouchScreen connected to your system. diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 2e6bdfea016..6d7aa10d10f 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -44,7 +44,6 @@ static int lifebook_set_6byte_proto(const struct dmi_system_id *d) } static const struct dmi_system_id __initconst lifebook_dmi_table[] = { -#if defined(CONFIG_DMI) && defined(CONFIG_X86) { /* FLORA-ie 55mi */ .matches = { @@ -118,7 +117,6 @@ static const struct dmi_system_id __initconst lifebook_dmi_table[] = { }, }, { } -#endif }; void __init lifebook_module_init(void) -- cgit v1.2.3 From 3f58061d0160424d244e3a72258a1366ab4a8547 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 Dec 2009 23:15:51 -0800 Subject: Input: twl4030_keypad - switch to using threaded IRQ Signed-off-by: Felipe Balbi Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/twl4030_keypad.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index eeaa7acb9cf..21d6184efa9 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -253,14 +253,6 @@ static irqreturn_t do_kp_irq(int irq, void *_kp) u8 reg; int ret; -#ifdef CONFIG_LOCKDEP - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which - * we don't want and can't tolerate. Although it might be - * friendlier not to borrow this thread context... - */ - local_irq_enable(); -#endif - /* Read & Clear TWL4030 pending interrupt */ ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); @@ -403,7 +395,8 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) * * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... */ - error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp); + error = request_threaded_irq(kp->irq, NULL, do_kp_irq, + 0, pdev->name, kp); if (error) { dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", kp->irq); -- cgit v1.2.3 From 70f944139084c4f297ac90b3af4cb67a8a68b2cf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 29 Dec 2009 23:16:28 -0800 Subject: Input: twl4030-pwrbutton - switch to using threaded IRQ Signed-off-by: Felipe Balbi Signed-off-by: Dmitry Torokhov --- drivers/input/misc/twl4030-pwrbutton.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index bdde5c88903..e9069b87fde 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -39,18 +39,8 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) int err; u8 value; -#ifdef CONFIG_LOCKDEP - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which - * we don't want and can't tolerate since this is a threaded - * IRQ and can sleep due to the i2c reads it has to issue. - * Although it might be friendlier not to borrow this thread - * context... - */ - local_irq_enable(); -#endif - err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, - STS_HW_CONDITIONS); + STS_HW_CONDITIONS); if (!err) { input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); input_sync(pwr); @@ -80,7 +70,7 @@ static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev) pwr->phys = "twl4030_pwrbutton/input0"; pwr->dev.parent = &pdev->dev; - err = request_irq(irq, powerbutton_irq, + err = request_threaded_irq(irq, NULL, powerbutton_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "twl4030_pwrbutton", pwr); if (err < 0) { -- cgit v1.2.3 From abb631bfe271a9102fb5b05419272b7aec37a974 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 26 Dec 2009 21:51:38 -0500 Subject: dell-wmi: sys_init_module: 'dell_wmi'->init suspiciously returned 21, it should follow 0/-E convention wmi_install_notify_handler() returns an acpi_error, but dell_wmi_init() needs return a -errno style error. Tested-by: Paul Rolland Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 916ccb2b316..4c7e70299d6 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -323,6 +323,7 @@ static int __init dell_wmi_input_setup(void) static int __init dell_wmi_init(void) { int err; + acpi_status status; if (wmi_has_guid(DELL_EVENT_GUID)) { printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); @@ -336,14 +337,14 @@ static int __init dell_wmi_init(void) if (err) return err; - err = wmi_install_notify_handler(DELL_EVENT_GUID, + status = wmi_install_notify_handler(DELL_EVENT_GUID, dell_wmi_notify, NULL); - if (err) { + if (ACPI_FAILURE(status)) { input_unregister_device(dell_wmi_input_dev); printk(KERN_ERR "dell-wmi: Unable to register notify handler - %d\n", - err); - return err; + status); + return -ENODEV; } return 0; -- cgit v1.2.3 From f27725756be8a2c2dc65eaf70d0b52807aa2f113 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 26 Dec 2009 22:04:03 -0500 Subject: ACPI: hp-wmi, msi-wmi: clarify that wmi_install_notify_handler() returns an acpi_status Emphasize that that wmi_install_notify_handler() returns an acpi_status rather than -errno by by testing ACPI_SUCCESS(), ACPI_FAILURE(). No functional change in this patch, but this confusion caused a bug in dell-wmi. Signed-off-by: Len Brown --- drivers/platform/x86/hp-wmi.c | 2 +- drivers/platform/x86/msi-wmi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 8781d8fa7a5..18bf74136d2 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -581,7 +581,7 @@ static int __init hp_wmi_init(void) if (wmi_has_guid(HPWMI_EVENT_GUID)) { err = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL); - if (!err) + if (ACPI_SUCCESS(err)) hp_wmi_input_setup(); } diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 7f77f908bb0..f746c677ada 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -236,7 +236,7 @@ static int __init msi_wmi_init(void) } err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, msi_wmi_notify, NULL); - if (err) + if (ACPI_FAILURE(err)) return -EINVAL; err = msi_wmi_input_setup(); -- cgit v1.2.3 From fda11e61ff8a4e3a8ebbd434e46560b67cc0ca9d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 26 Dec 2009 23:02:24 -0500 Subject: dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value When acpi_evaluate_object() is passed ACPI_ALLOCATE_BUFFER, the caller must kfree the returned buffer if AE_OK is returned. The callers of wmi_get_event_data() pass ACPI_ALLOCATE_BUFFER, and thus must check its return value before accessing or kfree() on the buffer. Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 7 ++++++- drivers/platform/x86/hp-wmi.c | 7 ++++++- drivers/platform/x86/msi-wmi.c | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 4c7e70299d6..500af8c9ada 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -202,8 +202,13 @@ static void dell_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO "dell-wmi: bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 18bf74136d2..5b648f0c607 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -338,8 +338,13 @@ static void hp_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; int eventcode; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO "hp-wmi: bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index f746c677ada..f5f70d4c691 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -149,8 +149,13 @@ static void msi_wmi_notify(u32 value, void *context) static struct key_entry *key; union acpi_object *obj; ktime_t cur; + acpi_status status; - wmi_get_event_data(value, &response); + status = wmi_get_event_data(value, &response); + if (status != AE_OK) { + printk(KERN_INFO DRV_PFX "bad event status 0x%x\n", status); + return; + } obj = (union acpi_object *)response.pointer; -- cgit v1.2.3 From c03b26a5a5597a59b2e247d005d5901430109a8a Mon Sep 17 00:00:00 2001 From: Paul Rolland Date: Wed, 30 Dec 2009 01:07:40 -0500 Subject: wmi: check find_guid() return value to prevent oops Signed-off-by: Paul Rolland Signed-off-by: Len Brown --- drivers/platform/x86/wmi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 9f93d6c0f51..cc9ad740bda 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -492,8 +492,7 @@ wmi_notify_handler handler, void *data) if (!guid || !handler) return AE_BAD_PARAMETER; - find_guid(guid, &block); - if (!block) + if (!find_guid(guid, &block)) return AE_NOT_EXIST; if (block->handler) @@ -521,8 +520,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!guid) return AE_BAD_PARAMETER; - find_guid(guid, &block); - if (!block) + if (!find_guid(guid, &block)) return AE_NOT_EXIST; if (!block->handler) -- cgit v1.2.3 From 7a9568f536754623738110a314ff33286cdbb17d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 25 Dec 2009 11:49:35 -0800 Subject: dell-wmi - fix condition to abort driver loading From: Dmitry Torokhov The commit 1fdd407f4e3f2ecb453954cbebb6c22491c61853 incorrectly made driver abort loading when known GUID is present when it should have done exactly the opposite. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 500af8c9ada..1b1dddbd574 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -330,7 +330,7 @@ static int __init dell_wmi_init(void) int err; acpi_status status; - if (wmi_has_guid(DELL_EVENT_GUID)) { + if (!wmi_has_guid(DELL_EVENT_GUID)) { printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); return -ENODEV; } -- cgit v1.2.3 From d1f9e4970742bb1e22d07b01bd44f9c357d25c42 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 26 Dec 2009 19:14:59 +0000 Subject: ACPI: WMI: Survive BIOS with duplicate GUIDs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It would appear that in BIOS's with nVidia hooks, the GUID 05901221-D566-11D1-B2F0-00A0C9062910 is duplicated. For now, the simplest solution is to just ignore any duplicate GUIDs. These particular hooks are not currently supported/ used in the kernel, so whoever does that can figure out what the 'right' solution should be (if there's a better one). http://bugzilla.kernel.org/show_bug.cgi?id=14846 Signed-off-by: Carlos Corbacho Reported-by: Larry Finger Reported-by: Oldřich Jedlička Signed-off-by: Len Brown --- drivers/platform/x86/wmi.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index cc9ad740bda..b104302fea0 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -714,6 +714,22 @@ static int wmi_class_init(void) return ret; } +static bool guid_already_parsed(const char *guid_string) +{ + struct guid_block *gblock; + struct wmi_block *wblock; + struct list_head *p; + + list_for_each(p, &wmi_blocks.list) { + wblock = list_entry(p, struct wmi_block, list); + gblock = &wblock->gblock; + + if (strncmp(gblock->guid, guid_string, 16) == 0) + return true; + } + return false; +} + /* * Parse the _WDG method for the GUID data blocks */ @@ -723,6 +739,7 @@ static __init acpi_status parse_wdg(acpi_handle handle) union acpi_object *obj; struct guid_block *gblock; struct wmi_block *wblock; + char guid_string[37]; acpi_status status; u32 i, total; @@ -745,6 +762,19 @@ static __init acpi_status parse_wdg(acpi_handle handle) memcpy(gblock, obj->buffer.pointer, obj->buffer.length); for (i = 0; i < total; i++) { + /* + Some WMI devices, like those for nVidia hooks, have a + duplicate GUID. It's not clear what we should do in this + case yet, so for now, we'll just ignore the duplicate. + Anyone who wants to add support for that device can come + up with a better workaround for the mess then. + */ + if (guid_already_parsed(gblock[i].guid) == true) { + wmi_gtoa(gblock[i].guid, guid_string); + printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n", + guid_string); + continue; + } wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); if (!wblock) return AE_NO_MEMORY; -- cgit v1.2.3 From f405d2c02395a74d3883bd03ded36457aa3697ad Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 28 Dec 2009 18:11:56 +0900 Subject: x86/agp: Fix agp_amd64_init() initialization with CONFIG_GART_IOMMU enabled with CONFIG_GART_IOMMU enabled drivers/char/agp/amd64-agp.c has: #ifndef CONFIG_GART_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); #endif agp_amd64_init() was called via gart_iommu_init with CONFIG_GART_IOMMU=y agp_amd64_init() was called via module_init with CONFIG_GART_IOMMU=n The commit 75f1cdf1dda92cae037ec848ae63690d91913eac changes the x86 dma initialization routine: gart_iommu_init() is called only when GART IOMMU is detected. So when GART IOMMU isn't detected, agp_amd64_init isn't called. Marin Mitov reported this issue: http://marc.info/?l=linux-kernel&m=126192729110083&w=2 With this patch, agp_amd64_init() is always called via module_init (the above ifndef is removed). If agp_amd64_init() is called via gart_iommu_init() earlier, agp_amd64_init() finishes without doing anything (when it is called via module_init). Reported-by: Marin Mitov Tested-by: Marin Mitov Signed-off-by: FUJITA Tomonori Cc: davej@redhat.com LKML-Reference: <20091228181118C.fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Ingo Molnar --- drivers/char/agp/amd64-agp.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 2fb2e6cc322..5aa7a586a7f 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,9 +725,14 @@ static struct pci_driver agp_amd64_pci_driver = { int __init agp_amd64_init(void) { int err = 0; + static int done = 0; if (agp_off) return -EINVAL; + + if (done++) + return agp_bridges_found ? 0 : -ENODEV; + err = pci_register_driver(&agp_amd64_pci_driver); if (err < 0) return err; @@ -771,12 +776,8 @@ static void __exit agp_amd64_cleanup(void) pci_unregister_driver(&agp_amd64_pci_driver); } -/* On AMD64 the PCI driver needs to initialize this driver early - for the IOMMU, so it has to be called via a backdoor. */ -#ifndef CONFIG_GART_IOMMU module_init(agp_amd64_init); module_exit(agp_amd64_cleanup); -#endif MODULE_AUTHOR("Dave Jones , Andi Kleen"); module_param(agp_try_unsupported, bool, 0); -- cgit v1.2.3 From 44214ab474671e1ab5a860954db413bce52f7e04 Mon Sep 17 00:00:00 2001 From: Rakesh Ranjan Date: Tue, 15 Dec 2009 12:19:19 +0530 Subject: [SCSI] cxgb3i: Fix a login over vlan issue Fix a target login issue, when parent interface is vlan and we are using cxgb3i sepecific private ip address in '/etc/iscsi/ifaces/' iface file. Signed-off-by: Rakesh Ranjan Acked-by: Karen Xie Signed-off-by: James Bottomley --- drivers/scsi/cxgb3i/cxgb3i_offload.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index 26ffdcd5a43..15a00e8b712 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -1440,6 +1440,10 @@ void cxgb3i_c3cn_release(struct s3_conn *c3cn) static int is_cxgb3_dev(struct net_device *dev) { struct cxgb3i_sdev_data *cdata; + struct net_device *ndev = dev; + + if (dev->priv_flags & IFF_802_1Q_VLAN) + ndev = vlan_dev_real_dev(dev); write_lock(&cdata_rwlock); list_for_each_entry(cdata, &cdata_list, list) { @@ -1447,7 +1451,7 @@ static int is_cxgb3_dev(struct net_device *dev) int i; for (i = 0; i < ports->nports; i++) - if (dev == ports->lldevs[i]) { + if (ndev == ports->lldevs[i]) { write_unlock(&cdata_rwlock); return 1; } @@ -1566,6 +1570,26 @@ out_err: return -EINVAL; } +/** + * cxgb3i_find_dev - find the interface associated with the given address + * @ipaddr: ip address + */ +static struct net_device * +cxgb3i_find_dev(struct net_device *dev, __be32 ipaddr) +{ + struct flowi fl; + int err; + struct rtable *rt; + + memset(&fl, 0, sizeof(fl)); + fl.nl_u.ip4_u.daddr = ipaddr; + + err = ip_route_output_key(dev ? dev_net(dev) : &init_net, &rt, &fl); + if (!err) + return (&rt->u.dst)->dev; + + return NULL; +} /** * cxgb3i_c3cn_connect - initiates an iscsi tcp connection to a given address @@ -1581,6 +1605,7 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn, struct cxgb3i_sdev_data *cdata; struct t3cdev *cdev; __be32 sipv4; + struct net_device *dstdev; int err; c3cn_conn_debug("c3cn 0x%p, dev 0x%p.\n", c3cn, dev); @@ -1591,6 +1616,13 @@ int cxgb3i_c3cn_connect(struct net_device *dev, struct s3_conn *c3cn, c3cn->daddr.sin_port = usin->sin_port; c3cn->daddr.sin_addr.s_addr = usin->sin_addr.s_addr; + dstdev = cxgb3i_find_dev(dev, usin->sin_addr.s_addr); + if (!dstdev || !is_cxgb3_dev(dstdev)) + return -ENETUNREACH; + + if (dstdev->priv_flags & IFF_802_1Q_VLAN) + dev = dstdev; + rt = find_route(dev, c3cn->saddr.sin_addr.s_addr, c3cn->daddr.sin_addr.s_addr, c3cn->saddr.sin_port, -- cgit v1.2.3 From 3064ff39b8121acbd731f64d046218ebf3c2f9c0 Mon Sep 17 00:00:00 2001 From: Michael Hernandez Date: Tue, 15 Dec 2009 21:29:44 -0800 Subject: [SCSI] qla2xxx: Get the link data rate explicitly during device resync. When the hba port gets logged out of the fabric, or other such transitional state when the physical link is still present, the driver doesn't receive a loop up asyn event (where the link data rate currently gets set). Hence send a explicit mailbox command to get the link rate in such conditions. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 2 ++ drivers/scsi/qla2xxx/qla_mbx.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0b6801fc638..f61fb8d0133 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -324,6 +324,7 @@ qla2x00_read_ram_word(scsi_qla_host_t *, uint32_t, uint32_t *); extern int qla2x00_write_ram_word(scsi_qla_host_t *, uint32_t, uint32_t); +extern int qla2x00_get_data_rate(scsi_qla_host_t *); /* * Global Function Prototypes in qla_isr.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 73a793539d4..0f7ea6cc02f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2266,6 +2266,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha) clear_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); clear_bit(RSCN_UPDATE, &vha->dpc_flags); + qla2x00_get_data_rate(vha); + /* Determine what we need to do */ if (ha->current_topology == ISP_CFG_FL && (test_bit(LOCAL_LOOP_UPDATE, &flags))) { diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 05d595d9a7e..e91f3d82b2f 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3643,3 +3643,36 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data) return rval; } + +int +qla2x00_get_data_rate(scsi_qla_host_t *vha) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + struct qla_hw_data *ha = vha->hw; + + if (!IS_FWI2_CAPABLE(ha)) + return QLA_FUNCTION_FAILED; + + DEBUG11(printk(KERN_INFO "%s(%ld): entered.\n", __func__, vha->host_no)); + + mcp->mb[0] = MBC_DATA_RATE; + mcp->mb[1] = 0; + mcp->out_mb = MBX_1|MBX_0; + mcp->in_mb = MBX_2|MBX_1|MBX_0; + mcp->tov = MBX_TOV_SECONDS; + mcp->flags = 0; + rval = qla2x00_mailbox_command(vha, mcp); + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk(KERN_INFO "%s(%ld): failed=%x mb[0]=%x.\n", + __func__, vha->host_no, rval, mcp->mb[0])); + } else { + DEBUG11(printk(KERN_INFO + "%s(%ld): done.\n", __func__, vha->host_no)); + if (mcp->mb[1] != 0x7) + ha->link_data_rate = mcp->mb[1]; + } + + return rval; +} -- cgit v1.2.3 From 5c66f5d193f68c2a7da0f2ad3535ed30ab14307b Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Tue, 15 Dec 2009 21:29:45 -0800 Subject: [SCSI] qla2xxx: Fix for a multiqueue bug in CPU affinity mode Hold the hardware lock while do the response completion in work queue threads as it involves sharing a common request queue among multiple threads. Signed-off-by: Anirban Chakraborty Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 2a4c7f4e7b6..b901aa267e7 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -639,8 +639,10 @@ static void qla_do_work(struct work_struct *work) struct rsp_que *rsp = container_of(work, struct rsp_que, q_work); struct scsi_qla_host *vha; + spin_lock_irq(&rsp->hw->hardware_lock); vha = qla25xx_get_host(rsp); qla24xx_process_response_queue(vha, rsp); + spin_unlock_irq(&rsp->hw->hardware_lock); } /* create response queue */ -- cgit v1.2.3 From 858808019313f217d63ec4ad26686e6fb7b08c19 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Tue, 15 Dec 2009 21:29:46 -0800 Subject: [SCSI] qla2xxx: Extend base EEH support in qla2xxx. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 32 +++++++++++++--- drivers/scsi/qla2xxx/qla_dbg.h | 9 ++++- drivers/scsi/qla2xxx/qla_def.h | 2 + drivers/scsi/qla2xxx/qla_init.c | 20 ++++++++++ drivers/scsi/qla2xxx/qla_isr.c | 9 +++-- drivers/scsi/qla2xxx/qla_mbx.c | 31 +++++++++++++-- drivers/scsi/qla2xxx/qla_os.c | 83 +++++++++++++++++++++++++++++++++++++---- 7 files changed, 165 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 21e2bc4d740..3a9f5b288ae 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -232,6 +232,9 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (off) return 0; + if (unlikely(pci_channel_offline(ha->pdev))) + return 0; + if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) return -EINVAL; if (start > ha->optrom_size) @@ -379,6 +382,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, struct device, kobj))); struct qla_hw_data *ha = vha->hw; + if (unlikely(pci_channel_offline(ha->pdev))) + return 0; + if (!capable(CAP_SYS_ADMIN)) return 0; @@ -398,6 +404,9 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, struct qla_hw_data *ha = vha->hw; uint8_t *tmp_data; + if (unlikely(pci_channel_offline(ha->pdev))) + return 0; + if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size || !ha->isp_ops->write_nvram) return 0; @@ -1238,10 +1247,11 @@ qla2x00_fw_state_show(struct device *dev, struct device_attribute *attr, char *buf) { scsi_qla_host_t *vha = shost_priv(class_to_shost(dev)); - int rval; + int rval = QLA_FUNCTION_FAILED; uint16_t state[5]; - rval = qla2x00_get_firmware_state(vha, state); + if (!vha->hw->flags.eeh_busy) + rval = qla2x00_get_firmware_state(vha, state); if (rval != QLA_SUCCESS) memset(state, -1, sizeof(state)); @@ -1452,10 +1462,13 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) if (!fcport) return; - if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) + if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) + return; + + if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); - else - qla2x00_abort_fcport_cmds(fcport); + return; + } /* * Transport has effectively 'deleted' the rport, clear @@ -1475,6 +1488,9 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) if (!fcport) return; + if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags)) + return; + if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) { qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16); return; @@ -1515,6 +1531,12 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) pfc_host_stat = &ha->fc_host_stat; memset(pfc_host_stat, -1, sizeof(struct fc_host_statistics)); + if (test_bit(UNLOADING, &vha->dpc_flags)) + goto done; + + if (unlikely(pci_channel_offline(ha->pdev))) + goto done; + stats = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &stats_dma); if (stats == NULL) { DEBUG2_3_11(printk("%s(%ld): Failed to allocate memory.\n", diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index f660dd70b72..d6d9c86cb05 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -26,7 +26,7 @@ /* #define QL_DEBUG_LEVEL_14 */ /* Output RSCN trace msgs */ /* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */ /* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */ -/* #define QL_DEBUG_LEVEL_17 */ /* Output MULTI-Q trace messages */ +/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */ /* * Macros use for debugging the driver. @@ -132,6 +132,13 @@ #else #define DEBUG16(x) do {} while (0) #endif + +#if defined(QL_DEBUG_LEVEL_17) +#define DEBUG17(x) do {x;} while (0) +#else +#define DEBUG17(x) do {} while (0) +#endif + /* * Firmware Dump structure definition */ diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 384afda7dbe..608e675f68c 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2256,11 +2256,13 @@ struct qla_hw_data { uint32_t disable_serdes :1; uint32_t gpsc_supported :1; uint32_t npiv_supported :1; + uint32_t pci_channel_io_perm_failure :1; uint32_t fce_enabled :1; uint32_t fac_supported :1; uint32_t chip_reset_done :1; uint32_t port0 :1; uint32_t running_gold_fw :1; + uint32_t eeh_busy :1; uint32_t cpu_affinity_enabled :1; uint32_t disable_msix_handshake :1; } flags; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 0f7ea6cc02f..b4a0eac8f96 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -269,6 +269,8 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) vha->flags.online = 0; ha->flags.chip_reset_done = 0; vha->flags.reset_active = 0; + ha->flags.pci_channel_io_perm_failure = 0; + ha->flags.eeh_busy = 0; atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); atomic_set(&vha->loop_state, LOOP_DOWN); vha->device_flags = DFLG_NO_CABLE; @@ -581,6 +583,9 @@ qla2x00_reset_chip(scsi_qla_host_t *vha) uint32_t cnt; uint16_t cmd; + if (unlikely(pci_channel_offline(ha->pdev))) + return; + ha->isp_ops->disable_intrs(ha); spin_lock_irqsave(&ha->hardware_lock, flags); @@ -786,6 +791,12 @@ void qla24xx_reset_chip(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + + if (pci_channel_offline(ha->pdev) && + ha->flags.pci_channel_io_perm_failure) { + return; + } + ha->isp_ops->disable_intrs(ha); /* Perform RISC reset. */ @@ -3562,6 +3573,13 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) /* Requeue all commands in outstanding command list. */ qla2x00_abort_all_cmds(vha, DID_RESET << 16); + if (unlikely(pci_channel_offline(ha->pdev) && + ha->flags.pci_channel_io_perm_failure)) { + clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags); + status = 0; + return status; + } + ha->isp_ops->get_flash_version(vha, req->ring); ha->isp_ops->nvram_config(vha); @@ -4460,6 +4478,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *vha) int ret, retries; struct qla_hw_data *ha = vha->hw; + if (ha->flags.pci_channel_io_perm_failure) + return; if (!IS_FWI2_CAPABLE(ha)) return; if (!ha->fw_major_version) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 1692a883f4d..ffd0efdff40 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -152,7 +152,7 @@ qla2300_intr_handler(int irq, void *dev_id) for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_PAUSED) { - if (pci_channel_offline(ha->pdev)) + if (unlikely(pci_channel_offline(ha->pdev))) break; hccr = RD_REG_WORD(®->hccr); @@ -1846,12 +1846,15 @@ qla24xx_intr_handler(int irq, void *dev_id) reg = &ha->iobase->isp24; status = 0; + if (unlikely(pci_channel_offline(ha->pdev))) + return IRQ_HANDLED; + spin_lock_irqsave(&ha->hardware_lock, flags); vha = pci_get_drvdata(ha->pdev); for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { - if (pci_channel_offline(ha->pdev)) + if (unlikely(pci_channel_offline(ha->pdev))) break; hccr = RD_REG_DWORD(®->hccr); @@ -1992,7 +1995,7 @@ qla24xx_msix_default(int irq, void *dev_id) do { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { - if (pci_channel_offline(ha->pdev)) + if (unlikely(pci_channel_offline(ha->pdev))) break; hccr = RD_REG_DWORD(®->hccr); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index e91f3d82b2f..056e4d4505f 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -56,6 +56,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) DEBUG11(printk("%s(%ld): entered.\n", __func__, base_vha->host_no)); + if (ha->flags.pci_channel_io_perm_failure) { + DEBUG(printk("%s(%ld): Perm failure on EEH, timeout MBX " + "Exiting.\n", __func__, vha->host_no)); + return QLA_FUNCTION_TIMEOUT; + } + /* * Wait for active mailbox commands to finish by waiting at most tov * seconds. This is to serialize actual issuing of mailbox cmds during @@ -154,10 +160,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) /* Check for pending interrupts. */ qla2x00_poll(ha->rsp_q_map[0]); - if (command != MBC_LOAD_RISC_RAM_EXTENDED && - !ha->flags.mbox_int) + if (!ha->flags.mbox_int && + !(IS_QLA2200(ha) && + command == MBC_LOAD_RISC_RAM_EXTENDED)) msleep(10); } /* while */ + DEBUG17(qla_printk(KERN_WARNING, ha, + "Waited %d sec\n", + (uint)((jiffies - (wait_time - (mcp->tov * HZ)))/HZ))); } /* Check whether we timed out */ @@ -227,7 +237,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) if (rval == QLA_FUNCTION_TIMEOUT && mcp->mb[0] != MBC_GEN_SYSTEM_ERROR) { - if (!io_lock_on || (mcp->flags & IOCTL_CMD)) { + if (!io_lock_on || (mcp->flags & IOCTL_CMD) || + ha->flags.eeh_busy) { /* not in dpc. schedule it for dpc to take over. */ DEBUG(printk("%s(%ld): timeout schedule " "isp_abort_needed.\n", __func__, @@ -237,7 +248,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) base_vha->host_no)); qla_printk(KERN_WARNING, ha, "Mailbox command timeout occurred. Scheduling ISP " - "abort.\n"); + "abort. eeh_busy: 0x%x\n", ha->flags.eeh_busy); set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); qla2xxx_wake_dpc(vha); } else if (!abort_active) { @@ -2530,6 +2541,9 @@ qla2x00_enable_eft_trace(scsi_qla_host_t *vha, dma_addr_t eft_dma, if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; + if (unlikely(pci_channel_offline(vha->hw->pdev))) + return QLA_FUNCTION_FAILED; + DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); mcp->mb[0] = MBC_TRACE_CONTROL; @@ -2565,6 +2579,9 @@ qla2x00_disable_eft_trace(scsi_qla_host_t *vha) if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; + if (unlikely(pci_channel_offline(vha->hw->pdev))) + return QLA_FUNCTION_FAILED; + DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); mcp->mb[0] = MBC_TRACE_CONTROL; @@ -2595,6 +2612,9 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma, if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw)) return QLA_FUNCTION_FAILED; + if (unlikely(pci_channel_offline(vha->hw->pdev))) + return QLA_FUNCTION_FAILED; + DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); mcp->mb[0] = MBC_TRACE_CONTROL; @@ -2639,6 +2659,9 @@ qla2x00_disable_fce_trace(scsi_qla_host_t *vha, uint64_t *wr, uint64_t *rd) if (!IS_FWI2_CAPABLE(vha->hw)) return QLA_FUNCTION_FAILED; + if (unlikely(pci_channel_offline(vha->hw->pdev))) + return QLA_FUNCTION_FAILED; + DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no)); mcp->mb[0] = MBC_TRACE_CONTROL; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2f873d23732..1ab358210c6 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -475,11 +475,11 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) srb_t *sp; int rval; - if (unlikely(pci_channel_offline(ha->pdev))) { - if (ha->pdev->error_state == pci_channel_io_frozen) - cmd->result = DID_REQUEUE << 16; - else + if (ha->flags.eeh_busy) { + if (ha->flags.pci_channel_io_perm_failure) cmd->result = DID_NO_CONNECT << 16; + else + cmd->result = DID_REQUEUE << 16; goto qc24_fail_command; } @@ -552,8 +552,15 @@ qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd) #define ABORT_POLLING_PERIOD 1000 #define ABORT_WAIT_ITER ((10 * 1000) / (ABORT_POLLING_PERIOD)) unsigned long wait_iter = ABORT_WAIT_ITER; + scsi_qla_host_t *vha = shost_priv(cmd->device->host); + struct qla_hw_data *ha = vha->hw; int ret = QLA_SUCCESS; + if (unlikely(pci_channel_offline(ha->pdev)) || ha->flags.eeh_busy) { + DEBUG17(qla_printk(KERN_WARNING, ha, "return:eh_wait\n")); + return ret; + } + while (CMD_SP(cmd) && wait_iter--) { msleep(ABORT_POLLING_PERIOD); } @@ -2174,6 +2181,24 @@ qla2x00_free_device(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); + + /* Disable timer */ + if (vha->timer_active) + qla2x00_stop_timer(vha); + + /* Kill the kernel thread for this host */ + if (ha->dpc_thread) { + struct task_struct *t = ha->dpc_thread; + + /* + * qla2xxx_wake_dpc checks for ->dpc_thread + * so we need to zero it out. + */ + ha->dpc_thread = NULL; + kthread_stop(t); + } + qla25xx_delete_queues(vha); if (ha->flags.fce_enabled) @@ -2185,6 +2210,8 @@ qla2x00_free_device(scsi_qla_host_t *vha) /* Stop currently executing firmware. */ qla2x00_try_to_stop_firmware(vha); + vha->flags.online = 0; + /* turn-off interrupts on the card */ if (ha->interrupts_on) ha->isp_ops->disable_intrs(ha); @@ -2859,6 +2886,13 @@ qla2x00_do_dpc(void *data) if (!base_vha->flags.init_done) continue; + if (ha->flags.eeh_busy) { + DEBUG17(qla_printk(KERN_WARNING, ha, + "qla2x00_do_dpc: dpc_flags: %lx\n", + base_vha->dpc_flags)); + continue; + } + DEBUG3(printk("scsi(%ld): DPC handler\n", base_vha->host_no)); ha->dpc_active = 1; @@ -3049,8 +3083,13 @@ qla2x00_timer(scsi_qla_host_t *vha) int index; srb_t *sp; int t; + uint16_t w; struct qla_hw_data *ha = vha->hw; struct req_que *req; + + /* Hardware read to raise pending EEH errors during mailbox waits. */ + if (!pci_channel_offline(ha->pdev)) + pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); /* * Ports - Port down timer. * @@ -3252,16 +3291,23 @@ qla2x00_release_firmware(void) static pci_ers_result_t qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { - scsi_qla_host_t *base_vha = pci_get_drvdata(pdev); + scsi_qla_host_t *vha = pci_get_drvdata(pdev); + struct qla_hw_data *ha = vha->hw; + + DEBUG2(qla_printk(KERN_WARNING, ha, "error_detected:state %x\n", + state)); switch (state) { case pci_channel_io_normal: + ha->flags.eeh_busy = 0; return PCI_ERS_RESULT_CAN_RECOVER; case pci_channel_io_frozen: + ha->flags.eeh_busy = 1; pci_disable_device(pdev); return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: - qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); + ha->flags.pci_channel_io_perm_failure = 1; + qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16); return PCI_ERS_RESULT_DISCONNECT; } return PCI_ERS_RESULT_NEED_RESET; @@ -3312,6 +3358,8 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev) struct qla_hw_data *ha = base_vha->hw; int rc; + DEBUG17(qla_printk(KERN_WARNING, ha, "slot_reset\n")); + if (ha->mem_only) rc = pci_enable_device_mem(pdev); else @@ -3320,19 +3368,33 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev) if (rc) { qla_printk(KERN_WARNING, ha, "Can't re-enable PCI device after reset.\n"); - return ret; } - pci_set_master(pdev); if (ha->isp_ops->pci_config(base_vha)) return ret; +#ifdef QL_DEBUG_LEVEL_17 + { + uint8_t b; + uint32_t i; + + printk("slot_reset_1: "); + for (i = 0; i < 256; i++) { + pci_read_config_byte(ha->pdev, i, &b); + printk("%s%02x", (i%16) ? " " : "\n", b); + } + printk("\n"); + } +#endif set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); if (qla2x00_abort_isp(base_vha) == QLA_SUCCESS) ret = PCI_ERS_RESULT_RECOVERED; clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); + DEBUG17(qla_printk(KERN_WARNING, ha, + "slot_reset-return:ret=%x\n", ret)); + return ret; } @@ -3343,12 +3405,17 @@ qla2xxx_pci_resume(struct pci_dev *pdev) struct qla_hw_data *ha = base_vha->hw; int ret; + DEBUG17(qla_printk(KERN_WARNING, ha, "pci_resume\n")); + ret = qla2x00_wait_for_hba_online(base_vha); if (ret != QLA_SUCCESS) { qla_printk(KERN_ERR, ha, "the device failed to resume I/O " "from slot/link_reset"); } + + ha->flags.eeh_busy = 0; + pci_cleanup_aer_uncorrect_error_status(pdev); } -- cgit v1.2.3 From ca79cf664806d833e28c8c05824b2361f59b8bc8 Mon Sep 17 00:00:00 2001 From: Duane Grigsby Date: Tue, 15 Dec 2009 21:29:47 -0800 Subject: [SCSI] qla2xxx: Added to EEH support. Added fundamental reset and pci save state. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 1ab358210c6..209f50e788a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1817,6 +1817,13 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); + + /* Set EEH reset type to fundamental if required by hba */ + if ( IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha)) { + pdev->needs_freset = 1; + pci_save_state(pdev); + } + /* Configure PCI I/O space */ ret = qla2x00_iospace_config(ha); if (ret) -- cgit v1.2.3 From 3b9c212a5cbb1e13ced92639ce83f7a48b8b2331 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Tue, 15 Dec 2009 21:29:48 -0800 Subject: [SCSI] qla2xxx: Update version number to 8.03.01-k9. Signed-off-by: Giridhar Malavali Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index c482220f7ee..a65dd95507c 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.01-k8" +#define QLA2XXX_VERSION "8.03.01-k9" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -- cgit v1.2.3 From a70757ba9a3719f99760713c3b72134b21016c6e Mon Sep 17 00:00:00 2001 From: Anil Ravindranath Date: Thu, 17 Dec 2009 14:51:53 -0800 Subject: [SCSI] pmcraid: fix to avoid twice scsi_dma_unmap for a command For a particular driver error condition, driver was doing double scsi_dma_unmaps. Driver was calling scsi_dma_unmap in pmcraid_error_handler and return 0. This pmcraid_error_handler is called by pmcraid_io_done which will do scsi_dma_unmap again when it has return 0 from pmcraid_error_handler. Signed-off-by: James Bottomley --- drivers/scsi/pmcraid.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index e7d2688fbeb..b6f1ef954af 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -2483,14 +2483,12 @@ static int pmcraid_error_handler(struct pmcraid_cmd *cmd) sense_copied = 1; } - if (RES_IS_GSCSI(res->cfg_entry)) { + if (RES_IS_GSCSI(res->cfg_entry)) pmcraid_cancel_all(cmd, sense_copied); - } else if (sense_copied) { + else if (sense_copied) pmcraid_erp_done(cmd); - return 0; - } else { + else pmcraid_request_sense(cmd); - } return 1; -- cgit v1.2.3 From c2b27ef672992a206e5b221b8676972dd840ffa5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 30 Dec 2009 12:18:24 -0800 Subject: Input: iforce - wait for command completion when closing the device We need to wait for the command to disable FF effects to complete before continuing with closing the device. Tested-by: Johannes Ebke Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/iforce/iforce-main.c | 3 +++ drivers/input/joystick/iforce/iforce-usb.c | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index acc3a9efb00..b1edd778639 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -228,6 +228,9 @@ static void iforce_close(struct input_dev *dev) /* Disable force feedback playback */ iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); + /* Wait for the command to complete */ + wait_event_interruptible(iforce->wait, + !test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)); } switch (iforce->bus) { diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index c0ad8836944..b41303d3ec5 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -109,6 +109,7 @@ static void iforce_usb_out(struct urb *urb) struct iforce *iforce = urb->context; if (urb->status) { + clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); dbg("urb->status %d, exiting", urb->status); return; } -- cgit v1.2.3 From b58454ec25e80fdb84e294758aeb22dd6d5ee6f9 Mon Sep 17 00:00:00 2001 From: Paul Rolland Date: Wed, 30 Dec 2009 01:19:12 -0500 Subject: wmi: check find_guid() return value to prevent oops Signed-off-by: rol@as2917.net Signed-off-by: Len Brown Signed-off-by: Linus Torvalds --- drivers/platform/x86/wmi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 9f93d6c0f51..cc9ad740bda 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -492,8 +492,7 @@ wmi_notify_handler handler, void *data) if (!guid || !handler) return AE_BAD_PARAMETER; - find_guid(guid, &block); - if (!block) + if (!find_guid(guid, &block)) return AE_NOT_EXIST; if (block->handler) @@ -521,8 +520,7 @@ acpi_status wmi_remove_notify_handler(const char *guid) if (!guid) return AE_BAD_PARAMETER; - find_guid(guid, &block); - if (!block) + if (!find_guid(guid, &block)) return AE_NOT_EXIST; if (!block->handler) -- cgit v1.2.3 From 5ccf73bb4dc7cc9e1f761202a34de5714164724f Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 30 Dec 2009 01:21:42 -0500 Subject: dell-wmi: sys_init_module: 'dell_wmi'->init suspiciously returned 21, it should follow 0/-E convention wmi_install_notify_handler() returns an acpi_error, but dell_wmi_init() needs return a -errno style error. Signed-off-by: Len Brown Tested-by: Paul Rolland Signed-off-by: Linus Torvalds --- drivers/platform/x86/dell-wmi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 916ccb2b316..4c7e70299d6 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -323,6 +323,7 @@ static int __init dell_wmi_input_setup(void) static int __init dell_wmi_init(void) { int err; + acpi_status status; if (wmi_has_guid(DELL_EVENT_GUID)) { printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); @@ -336,14 +337,14 @@ static int __init dell_wmi_init(void) if (err) return err; - err = wmi_install_notify_handler(DELL_EVENT_GUID, + status = wmi_install_notify_handler(DELL_EVENT_GUID, dell_wmi_notify, NULL); - if (err) { + if (ACPI_FAILURE(status)) { input_unregister_device(dell_wmi_input_dev); printk(KERN_ERR "dell-wmi: Unable to register notify handler - %d\n", - err); - return err; + status); + return -ENODEV; } return 0; -- cgit v1.2.3 From d7f0eea9e431e1b8b0742a74db1a9490730b2a25 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Dec 2009 15:36:42 +0800 Subject: ACPI: introduce kernel parameter acpi_sleep=sci_force_enable Introduce kernel parameter acpi_sleep=sci_force_enable some laptop requires SCI_EN being set directly on resume, or else they hung somewhere in the resume code path. We already have a blacklist for these laptops but we still need this option, especially when debugging some suspend/resume problems, in case there are systems that need this workaround and are not yet in the blacklist. Signed-off-by: Zhang Rui Acked-by: Rafael J. Wysocki Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 5f2c379ab7b..79d33d908b5 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -80,6 +80,23 @@ static int acpi_sleep_prepare(u32 acpi_state) #ifdef CONFIG_ACPI_SLEEP static u32 acpi_target_sleep_state = ACPI_STATE_S0; +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + +void __init acpi_set_sci_en_on_resume(void) +{ + set_sci_en_on_resume = true; +} + /* * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the * user to request that behavior by using the 'acpi_old_suspend_ordering' @@ -170,18 +187,6 @@ static void acpi_pm_end(void) #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND -/* - * According to the ACPI specification the BIOS should make sure that ACPI is - * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, - * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI - * on such systems during resume. Unfortunately that doesn't help in - * particularly pathological cases in which SCI_EN has to be set directly on - * resume, although the specification states very clearly that this flag is - * owned by the hardware. The set_sci_en_on_resume variable will be set in such - * cases. - */ -static bool set_sci_en_on_resume; - extern void do_suspend_lowlevel(void); static u32 acpi_suspend_states[] = { -- cgit v1.2.3 From 3b8cb427e9281790f36e847e46cb1d005a50cec0 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Mon, 14 Dec 2009 09:42:28 +0800 Subject: acpi_pad: fix error checks There are some fixes listed below: 1. When met a bogus BIOS, the return value of cpu number maybe is a negative value so that acpi_pad_pur get an unexpected result. 2. the return value of function acpi_pad_idle_cpus is useless. 3. enhance the process of create_power_saving_task/destroy_power_saving_task 4. Add more error checks when evaluating _PUR object. 5. one typo fix Signed-off-by: Chen Gong Acked-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/acpi_pad.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 0d2cdb86158..a7bd49f0f01 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -207,7 +207,7 @@ static int power_saving_thread(void *data) * the mechanism only works when all CPUs have RT task running, * as if one CPU hasn't RT task, RT task from other CPUs will * borrow CPU time from this CPU and cause RT task use > 95% - * CPU time. To make 'avoid staration' work, takes a nap here. + * CPU time. To make 'avoid starvation' work, takes a nap here. */ if (do_sleep) schedule_timeout_killable(HZ * idle_pct / 100); @@ -221,14 +221,18 @@ static struct task_struct *ps_tsks[NR_CPUS]; static unsigned int ps_tsk_num; static int create_power_saving_task(void) { + int rc = -ENOMEM; + ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, (void *)(unsigned long)ps_tsk_num, "power_saving/%d", ps_tsk_num); - if (ps_tsks[ps_tsk_num]) { + rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; + if (!rc) ps_tsk_num++; - return 0; - } - return -EINVAL; + else + ps_tsks[ps_tsk_num] = NULL; + + return rc; } static void destroy_power_saving_task(void) @@ -236,6 +240,7 @@ static void destroy_power_saving_task(void) if (ps_tsk_num > 0) { ps_tsk_num--; kthread_stop(ps_tsks[ps_tsk_num]); + ps_tsks[ps_tsk_num] = NULL; } } @@ -252,7 +257,7 @@ static void set_power_saving_task_num(unsigned int num) } } -static int acpi_pad_idle_cpus(unsigned int num_cpus) +static void acpi_pad_idle_cpus(unsigned int num_cpus) { get_online_cpus(); @@ -260,7 +265,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus) set_power_saving_task_num(num_cpus); put_online_cpus(); - return 0; } static uint32_t acpi_pad_idle_cpus_num(void) @@ -368,19 +372,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) static int acpi_pad_pur(acpi_handle handle, int *num_cpus) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; - acpi_status status; union acpi_object *package; int rev, num, ret = -EINVAL; - status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) + return -EINVAL; + + if (!buffer.length || !buffer.pointer) return -EINVAL; + 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) + if (rev != 1 || num < 0) goto out; *num_cpus = num; ret = 0; @@ -409,7 +415,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat, static void acpi_pad_handle_notify(acpi_handle handle) { - int num_cpus, ret; + int num_cpus; uint32_t idle_cpus; mutex_lock(&isolated_cpus_lock); @@ -417,12 +423,9 @@ static void acpi_pad_handle_notify(acpi_handle handle) mutex_unlock(&isolated_cpus_lock); return; } - ret = acpi_pad_idle_cpus(num_cpus); + acpi_pad_idle_cpus(num_cpus); idle_cpus = acpi_pad_idle_cpus_num(); - if (!ret) - acpi_pad_ost(handle, 0, idle_cpus); - else - acpi_pad_ost(handle, 1, 0); + acpi_pad_ost(handle, 0, idle_cpus); mutex_unlock(&isolated_cpus_lock); } -- cgit v1.2.3 From c504f8cb68eb0d6cde53ba043daff8cb34586493 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 30 Dec 2009 15:59:23 +0800 Subject: ACPI video: Prune dupe video devices, unless "video.allow_duplicates" Some buggy BIOS exports multiple ACPI video bus devices for the same VGA controller, and multiple backlight control methods as well. This messes up the ACPI video backlight control. http://bugzilla.kernel.org/show_bug.cgi?id=13577 With this patch applied, only the FIRST ACPI video bus device under a PCI device node is bind to ACPI video driver by default. If the first ACPI video bus device doesn't work well, we can use video.allow_duplicates=1 to go back to the old behavior. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 05dff631591..45e6a29c817 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -78,6 +78,13 @@ MODULE_LICENSE("GPL"); static int brightness_switch_enabled = 1; module_param(brightness_switch_enabled, bool, 0644); +/* + * By default, we don't allow duplicate ACPI video bus devices + * under the same VGA controller + */ +static int allow_duplicates; +module_param(allow_duplicates, bool, 0644); + static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); @@ -2233,11 +2240,47 @@ static int acpi_video_resume(struct acpi_device *device) return AE_OK; } +static acpi_status +acpi_video_bus_match(acpi_handle handle, u32 level, void *context, + void **return_value) +{ + struct acpi_device *device = context; + struct acpi_device *sibling; + int result; + + if (handle == device->handle) + return AE_CTRL_TERMINATE; + + result = acpi_bus_get_device(handle, &sibling); + if (result) + return AE_OK; + + if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) + return AE_ALREADY_EXISTS; + + return AE_OK; +} + static int acpi_video_bus_add(struct acpi_device *device) { struct acpi_video_bus *video; struct input_dev *input; int error; + acpi_status status; + + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, + device->parent->handle, 1, + acpi_video_bus_match, NULL, + device, NULL); + if (status == AE_ALREADY_EXISTS) { + printk(KERN_WARNING FW_BUG + "Duplicate ACPI video bus devices for the" + " same VGA controller, please try module " + "parameter \"video.allow_duplicates=1\"" + "if the current driver doesn't work.\n"); + if (!allow_duplicates) + return -ENODEV; + } video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); if (!video) -- cgit v1.2.3 From 367a8d738542b091228613751af0958ce25bbeb3 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 29 Dec 2009 15:56:01 +0100 Subject: drbd: Silenced an assert that could triggered after changing write ordering method Immediately after changing the write ordering method, the epoch can already be finished at this point. Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 259c1351b15..a6d266ee7e2 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1201,10 +1201,11 @@ static int receive_Barrier(struct drbd_conf *mdev, struct p_header *h) case WO_bdev_flush: case WO_drain_io: - D_ASSERT(rv == FE_STILL_LIVE); - set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags); - drbd_wait_ee_list_empty(mdev, &mdev->active_ee); - rv = drbd_flush_after_epoch(mdev, mdev->current_epoch); + if (rv == FE_STILL_LIVE) { + set_bit(DE_BARRIER_IN_NEXT_EPOCH_ISSUED, &mdev->current_epoch->flags); + drbd_wait_ee_list_empty(mdev, &mdev->active_ee); + rv = drbd_flush_after_epoch(mdev, mdev->current_epoch); + } if (rv == FE_RECYCLED) return TRUE; -- cgit v1.2.3 From 5b889bf237fca383b5807ad69fde3ad1e2287e42 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 31 Dec 2009 19:06:35 +0100 Subject: PCI: Fix build if quirks are not enabled After commit b9c3b266411d27f1a6466c19d146d08db576bfea ("PCI: support device-specific reset methods") the kernel build is broken if CONFIG_PCI_QUIRKS is unset. Fix this by moving pci_dev_specific_reset() to drivers/pci/quirks.c and providing an empty replacement for !CONFIG_PCI_QUIRKS builds. Signed-off-by: Rafael J. Wysocki Reported-by: Ingo Molnar Signed-off-by: Linus Torvalds --- drivers/pci/pci.c | 15 --------------- drivers/pci/pci.h | 2 +- drivers/pci/quirks.c | 19 ++++++++++++++++++- 3 files changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 864e703cf73..0906599ebfd 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2284,21 +2284,6 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe) return 0; } -static int pci_dev_specific_reset(struct pci_dev *dev, int probe) -{ - struct pci_dev_reset_methods *i; - - for (i = pci_dev_reset_methods; i->reset; i++) { - if ((i->vendor == dev->vendor || - i->vendor == (u16)PCI_ANY_ID) && - (i->device == dev->device || - i->device == (u16)PCI_ANY_ID)) - return i->reset(dev, probe); - } - - return -ENOTTY; -} - static int pci_dev_reset(struct pci_dev *dev, int probe) { int rc; diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 709eaa4fee5..fbd0e3adbca 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -319,6 +319,6 @@ struct pci_dev_reset_methods { int (*reset)(struct pci_dev *dev, int probe); }; -extern struct pci_dev_reset_methods pci_dev_reset_methods[]; +extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); #endif /* DRIVERS_PCI_H */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 8726698866b..5c449fc4db1 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2684,14 +2684,31 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed -struct pci_dev_reset_methods pci_dev_reset_methods[] = { +static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, reset_intel_82599_sfp_virtfn }, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, reset_intel_generic_dev }, { 0 } }; + +int pci_dev_specific_reset(struct pci_dev *dev, int probe) +{ + struct pci_dev_reset_methods *i; + + for (i = pci_dev_reset_methods; i->reset; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) + return i->reset(dev, probe); + } + + return -ENOTTY; +} + #else void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} +int pci_dev_specific_reset(struct pci_dev *dev, int probe) { return -ENOTTY; } #endif EXPORT_SYMBOL(pci_fixup_device); -- cgit v1.2.3 From df9d1e8a4379119cbc47c474f168b5103e404e17 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 31 Dec 2009 16:44:43 -0800 Subject: pci: avoid compiler warning in quirks.c Introduced by commit 5b889bf23 ("PCI: Fix build if quirks are not enabled"), which made the pci_dev_reset_methods[] array static and 'const', but didn't then change the code to match, and use a const pointer when moving it to quirks.c. Trivially fixed by just adding the required 'const' to the iterator variable. Reported-by: Stephen Rothwell Cc: Rafael J. Wysocki Signed-off-by: Linus Torvalds --- drivers/pci/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5c449fc4db1..c74694345b6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2694,7 +2694,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { int pci_dev_specific_reset(struct pci_dev *dev, int probe) { - struct pci_dev_reset_methods *i; + const struct pci_dev_reset_methods *i; for (i = pci_dev_reset_methods; i->reset; i++) { if ((i->vendor == dev->vendor || -- cgit v1.2.3 From cd6e125c58ae1561bedb6ea6f70b00d6c2599d62 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 31 Dec 2009 17:26:05 -0800 Subject: twl4030-irq.c: fix compiler warning due to raw-spinlock conversion Commit 239007b844 ("genirq: Convert irq_desc.lock to raw_spinlock") seems to have missed this driver, leaving it to use the normal spin-lock functions for the irq descriptor lock, which is now a raw lock. Reported-and-compile-tested-by: Stephen Rothwell Signed-off-by: Linus Torvalds --- drivers/mfd/twl4030-irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 20d29bafc9f..9df9a5ad38f 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -568,12 +568,12 @@ static void twl4030_sih_do_edge(struct work_struct *work) bytes[byte] &= ~(0x03 << off); - spin_lock_irq(&d->lock); + raw_spin_lock_irq(&d->lock); if (d->status & IRQ_TYPE_EDGE_RISING) bytes[byte] |= BIT(off + 1); if (d->status & IRQ_TYPE_EDGE_FALLING) bytes[byte] |= BIT(off + 0); - spin_unlock_irq(&d->lock); + raw_spin_unlock_irq(&d->lock); edge_change &= ~BIT(i); } -- cgit v1.2.3 From c9c041fcb1a4d69ed4791f00b57554eeb341d148 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Thu, 31 Dec 2009 16:41:33 +0100 Subject: hp-wmi: remove double free caused by merge conflict Commit 3e9b988e4edf065d39c1343937f717319b1c1065 "wmi: Free the allocated acpi objects through wmi_get_event_data" had the same purpose as commit 44ef00e6482e755f36629773abc2aee83a6f53e3 "hp-wmi: Fix two memleaks" This should solve this regression: http://bugzilla.kernel.org/show_bug.cgi?id=14890 Signed-off-by: Anisse Astier Reported-by: Sedat Dilek Signed-off-by: Len Brown --- drivers/platform/x86/hp-wmi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 5b648f0c607..ad4c414dbfb 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -393,8 +393,6 @@ static void hp_wmi_notify(u32 value, void *context) } else printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", eventcode); - - kfree(obj); } static int __init hp_wmi_input_setup(void) -- cgit v1.2.3 From abf2a117c67a67fbb611913a31109d0ff66ab073 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 1 Jan 2010 18:35:11 -0800 Subject: Input: gf2k - fix &&/|| confusion in gf2k_connect() This always evaluates to true. Signed-off-by: Roel Kluin Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/gf2k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 67c207f5b1a..45ac70eae0a 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) } #ifdef RESET_WORKS - if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) || + if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) && (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) { err = -ENODEV; goto fail2; -- cgit v1.2.3 From 6486cda6c6b15368e2c925d89b4e9ed13e67b91b Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 4 Jan 2010 09:05:42 +0100 Subject: [S390] qdio: convert global statistics to per-device stats Revamp the qdio performance statistics and move them from procfs to debugfs using the seq_file interface. Since the statistics are not intended for the general user the removal of /proc/qdio_perf should not surprise anyone. The per device statistics are disabled by default, writing 1 to //qdio//statistics enables the statistics for the given device. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/Makefile | 2 +- drivers/s390/cio/qdio.h | 36 +++++++++- drivers/s390/cio/qdio_debug.c | 114 +++++++++++++++++++++++++++--- drivers/s390/cio/qdio_main.c | 71 +++++++++---------- drivers/s390/cio/qdio_perf.c | 149 ---------------------------------------- drivers/s390/cio/qdio_perf.h | 62 ----------------- drivers/s390/cio/qdio_thinint.c | 8 +-- 7 files changed, 177 insertions(+), 265 deletions(-) delete mode 100644 drivers/s390/cio/qdio_perf.c delete mode 100644 drivers/s390/cio/qdio_perf.h (limited to 'drivers') diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index d033414f759..e1b700a1964 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile @@ -10,5 +10,5 @@ obj-y += ccw_device.o cmf.o obj-$(CONFIG_CHSC_SCH) += chsc_sch.o obj-$(CONFIG_CCWGROUP) += ccwgroup.o -qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_perf.o qdio_setup.o +qdio-objs := qdio_main.o qdio_thinint.o qdio_debug.o qdio_setup.o obj-$(CONFIG_QDIO) += qdio.o diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index ff7748a9199..44f2f6a97f3 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -182,6 +182,34 @@ struct scssc_area { u32:32; } __attribute__ ((packed)); +struct qdio_dev_perf_stat { + unsigned int adapter_int; + unsigned int qdio_int; + unsigned int pci_request_int; + + unsigned int tasklet_inbound; + unsigned int tasklet_inbound_resched; + unsigned int tasklet_inbound_resched2; + unsigned int tasklet_outbound; + + unsigned int siga_read; + unsigned int siga_write; + unsigned int siga_sync; + + unsigned int inbound_call; + unsigned int inbound_handler; + unsigned int stop_polling; + unsigned int inbound_queue_full; + unsigned int outbound_call; + unsigned int outbound_handler; + unsigned int fast_requeue; + unsigned int target_full; + unsigned int eqbs; + unsigned int eqbs_partial; + unsigned int sqbs; + unsigned int sqbs_partial; +}; + struct qdio_input_q { /* input buffer acknowledgement flag */ int polling; @@ -269,6 +297,7 @@ struct qdio_irq { u32 *dsci; /* address of device state change indicator */ struct ccw_device *cdev; struct dentry *debugfs_dev; + struct dentry *debugfs_perf; unsigned long int_parm; struct subchannel_id schid; @@ -286,9 +315,10 @@ struct qdio_irq { struct ciw aqueue; struct qdio_ssqd_desc ssqd_desc; - void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); + struct qdio_dev_perf_stat perf_stat; + int perf_stat_enabled; /* * Warning: Leave these members together at the end so they won't be * cleared in qdio_setup_irq. @@ -311,6 +341,10 @@ struct qdio_irq { (irq->qib.qfmt == QDIO_IQDIO_QFMT || \ css_general_characteristics.aif_osa) +#define qperf(qdev,attr) qdev->perf_stat.attr +#define qperf_inc(q,attr) if (q->irq_ptr->perf_stat_enabled) \ + q->irq_ptr->perf_stat.attr++ + /* the highest iqdio queue is used for multicast */ static inline int multicast_outbound(struct qdio_q *q) { diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index 76769978285..f49761ff9a0 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -55,13 +55,11 @@ static int qstat_show(struct seq_file *m, void *v) if (!q) return 0; - seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); - seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); - seq_printf(m, "ftc: %d\n", q->first_to_check); - seq_printf(m, "last_move: %d\n", q->last_move); - seq_printf(m, "polling: %d\n", q->u.in.polling); - seq_printf(m, "ack start: %d\n", q->u.in.ack_start); - seq_printf(m, "ack count: %d\n", q->u.in.ack_count); + seq_printf(m, "DSCI: %d nr_used: %d\n", + *(u32 *)q->irq_ptr->dsci, atomic_read(&q->nr_buf_used)); + seq_printf(m, "ftc: %d last_move: %d\n", q->first_to_check, q->last_move); + seq_printf(m, "polling: %d ack start: %d ack count: %d\n", + q->u.in.polling, q->u.in.ack_start, q->u.in.ack_count); seq_printf(m, "slsb buffer states:\n"); seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); @@ -110,7 +108,6 @@ static ssize_t qstat_seq_write(struct file *file, const char __user *buf, if (!q) return 0; - if (q->is_input_q) xchg(q->irq_ptr->dsci, 1); local_bh_disable(); @@ -134,6 +131,98 @@ static const struct file_operations debugfs_fops = { .release = single_release, }; +static char *qperf_names[] = { + "Assumed adapter interrupts", + "QDIO interrupts", + "Requested PCIs", + "Inbound tasklet runs", + "Inbound tasklet resched", + "Inbound tasklet resched2", + "Outbound tasklet runs", + "SIGA read", + "SIGA write", + "SIGA sync", + "Inbound calls", + "Inbound handler", + "Inbound stop_polling", + "Inbound queue full", + "Outbound calls", + "Outbound handler", + "Outbound fast_requeue", + "Outbound target_full", + "QEBSM eqbs", + "QEBSM eqbs partial", + "QEBSM sqbs", + "QEBSM sqbs partial" +}; + +static int qperf_show(struct seq_file *m, void *v) +{ + struct qdio_irq *irq_ptr = m->private; + unsigned int *stat; + int i; + + if (!irq_ptr) + return 0; + if (!irq_ptr->perf_stat_enabled) { + seq_printf(m, "disabled\n"); + return 0; + } + stat = (unsigned int *)&irq_ptr->perf_stat; + + for (i = 0; i < ARRAY_SIZE(qperf_names); i++) + seq_printf(m, "%26s:\t%u\n", + qperf_names[i], *(stat + i)); + return 0; +} + +static ssize_t qperf_seq_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *off) +{ + struct seq_file *seq = file->private_data; + struct qdio_irq *irq_ptr = seq->private; + unsigned long val; + char buf[8]; + int ret; + + if (!irq_ptr) + return 0; + if (count >= sizeof(buf)) + return -EINVAL; + if (copy_from_user(&buf, ubuf, count)) + return -EFAULT; + buf[count] = 0; + + ret = strict_strtoul(buf, 10, &val); + if (ret < 0) + return ret; + + switch (val) { + case 0: + irq_ptr->perf_stat_enabled = 0; + memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); + break; + case 1: + irq_ptr->perf_stat_enabled = 1; + break; + } + return count; +} + +static int qperf_seq_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, qperf_show, + filp->f_path.dentry->d_inode->i_private); +} + +static struct file_operations debugfs_perf_fops = { + .owner = THIS_MODULE, + .open = qperf_seq_open, + .read = seq_read, + .write = qperf_seq_write, + .llseek = seq_lseek, + .release = single_release, +}; static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) { char name[QDIO_DEBUGFS_NAME_LEN]; @@ -156,6 +245,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) debugfs_root); if (IS_ERR(irq_ptr->debugfs_dev)) irq_ptr->debugfs_dev = NULL; + + irq_ptr->debugfs_perf = debugfs_create_file("statistics", + S_IFREG | S_IRUGO | S_IWUSR, + irq_ptr->debugfs_dev, irq_ptr, + &debugfs_perf_fops); + if (IS_ERR(irq_ptr->debugfs_perf)) + irq_ptr->debugfs_perf = NULL; + for_each_input_queue(irq_ptr, q, i) setup_debugfs_entry(q, cdev); for_each_output_queue(irq_ptr, q, i) @@ -171,6 +268,7 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd debugfs_remove(q->debugfs_q); for_each_output_queue(irq_ptr, q, i) debugfs_remove(q->debugfs_q); + debugfs_remove(irq_ptr->debugfs_perf); debugfs_remove(irq_ptr->debugfs_dev); } diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index b2275c5000e..999fe80c405 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -22,7 +22,6 @@ #include "device.h" #include "qdio.h" #include "qdio_debug.h" -#include "qdio_perf.h" MODULE_AUTHOR("Utz Bacher ,"\ "Jan Glauber "); @@ -126,7 +125,7 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, int rc; BUG_ON(!q->irq_ptr->sch_token); - qdio_perf_stat_inc(&perf_stats.debug_eqbs_all); + qperf_inc(q, eqbs); if (!q->is_input_q) nr += q->irq_ptr->nr_input_qs; @@ -139,7 +138,7 @@ again: * buffers later. */ if ((ccq == 96) && (count != tmp_count)) { - qdio_perf_stat_inc(&perf_stats.debug_eqbs_incomplete); + qperf_inc(q, eqbs_partial); return (count - tmp_count); } @@ -182,7 +181,7 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start, return 0; BUG_ON(!q->irq_ptr->sch_token); - qdio_perf_stat_inc(&perf_stats.debug_sqbs_all); + qperf_inc(q, sqbs); if (!q->is_input_q) nr += q->irq_ptr->nr_input_qs; @@ -191,7 +190,7 @@ again: rc = qdio_check_ccq(q, ccq); if (rc == 1) { DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq); - qdio_perf_stat_inc(&perf_stats.debug_sqbs_incomplete); + qperf_inc(q, sqbs_partial); goto again; } if (rc < 0) { @@ -285,7 +284,7 @@ static inline int qdio_siga_sync(struct qdio_q *q, unsigned int output, return 0; DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr); - qdio_perf_stat_inc(&perf_stats.siga_sync); + qperf_inc(q, siga_sync); cc = do_siga_sync(q->irq_ptr->schid, output, input); if (cc) @@ -350,7 +349,7 @@ static inline int qdio_siga_input(struct qdio_q *q) int cc; DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr); - qdio_perf_stat_inc(&perf_stats.siga_in); + qperf_inc(q, siga_read); cc = do_siga_input(q->irq_ptr->schid, q->mask); if (cc) @@ -382,7 +381,7 @@ static inline void qdio_stop_polling(struct qdio_q *q) return; q->u.in.polling = 0; - qdio_perf_stat_inc(&perf_stats.debug_stop_polling); + qperf_inc(q, stop_polling); /* show the card that we are not polling anymore */ if (is_qebsm(q)) { @@ -400,7 +399,7 @@ static void announce_buffer_error(struct qdio_q *q, int count) /* special handling for no target buffer empty */ if ((!q->is_input_q && (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { - qdio_perf_stat_inc(&perf_stats.outbound_target_full); + qperf_inc(q, target_full); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", q->first_to_check); return; @@ -487,7 +486,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) inbound_primed(q, count); q->first_to_check = add_buf(q->first_to_check, count); if (atomic_sub(count, &q->nr_buf_used) == 0) - qdio_perf_stat_inc(&perf_stats.inbound_queue_full); + qperf_inc(q, inbound_queue_full); break; case SLSB_P_INPUT_ERROR: announce_buffer_error(q, count); @@ -567,9 +566,10 @@ static void qdio_kick_handler(struct qdio_q *q) count = sub_buf(end, start); if (q->is_input_q) { - qdio_perf_stat_inc(&perf_stats.inbound_handler); + qperf_inc(q, inbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); } else + qperf_inc(q, outbound_handler); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", start, count); @@ -583,24 +583,28 @@ static void qdio_kick_handler(struct qdio_q *q) static void __qdio_inbound_processing(struct qdio_q *q) { - qdio_perf_stat_inc(&perf_stats.tasklet_inbound); + qperf_inc(q, tasklet_inbound); again: if (!qdio_inbound_q_moved(q)) return; qdio_kick_handler(q); - if (!qdio_inbound_q_done(q)) + if (!qdio_inbound_q_done(q)) { /* means poll time is not yet over */ + qperf_inc(q, tasklet_inbound_resched); goto again; + } qdio_stop_polling(q); /* * We need to check again to not lose initiative after * resetting the ACK state. */ - if (!qdio_inbound_q_done(q)) + if (!qdio_inbound_q_done(q)) { + qperf_inc(q, tasklet_inbound_resched2); goto again; + } } void qdio_inbound_processing(unsigned long data) @@ -688,7 +692,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q) return 0; DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr); - qdio_perf_stat_inc(&perf_stats.siga_out); + qperf_inc(q, siga_write); cc = qdio_siga_output(q, &busy_bit); switch (cc) { @@ -711,7 +715,7 @@ static int qdio_kick_outbound_q(struct qdio_q *q) static void __qdio_outbound_processing(struct qdio_q *q) { - qdio_perf_stat_inc(&perf_stats.tasklet_outbound); + qperf_inc(q, tasklet_outbound); BUG_ON(atomic_read(&q->nr_buf_used) < 0); if (qdio_outbound_q_moved(q)) @@ -739,12 +743,9 @@ static void __qdio_outbound_processing(struct qdio_q *q) */ if (qdio_outbound_q_done(q)) del_timer(&q->u.out.timer); - else { - if (!timer_pending(&q->u.out.timer)) { + else + if (!timer_pending(&q->u.out.timer)) mod_timer(&q->u.out.timer, jiffies + 10 * HZ); - qdio_perf_stat_inc(&perf_stats.debug_tl_out_timer); - } - } return; sched: @@ -784,7 +785,7 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q) static void __tiqdio_inbound_processing(struct qdio_q *q) { - qdio_perf_stat_inc(&perf_stats.thinint_inbound); + qperf_inc(q, tasklet_inbound); qdio_sync_after_thinint(q); /* @@ -799,7 +800,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) qdio_kick_handler(q); if (!qdio_inbound_q_done(q)) { - qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); + qperf_inc(q, tasklet_inbound_resched); if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { tasklet_schedule(&q->tasklet); return; @@ -812,7 +813,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) * resetting the ACK state. */ if (!qdio_inbound_q_done(q)) { - qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop2); + qperf_inc(q, tasklet_inbound_resched2); if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) tasklet_schedule(&q->tasklet); } @@ -851,8 +852,6 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr) if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED)) return; - qdio_perf_stat_inc(&perf_stats.pci_int); - for_each_input_queue(irq_ptr, q, i) tasklet_schedule(&q->tasklet); @@ -923,8 +922,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, struct qdio_irq *irq_ptr = cdev->private->qdio_data; int cstat, dstat; - qdio_perf_stat_inc(&perf_stats.qdio_int); - if (!intparm || !irq_ptr) { DBF_ERROR("qint:%4x", cdev->private->schid.sch_no); return; @@ -1383,6 +1380,8 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags, { int used, diff; + qperf_inc(q, inbound_call); + if (!q->u.in.polling) goto set; @@ -1438,14 +1437,16 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, unsigned char state; int used, rc = 0; - qdio_perf_stat_inc(&perf_stats.outbound_handler); + qperf_inc(q, outbound_call); count = set_buf_states(q, bufnr, SLSB_CU_OUTPUT_PRIMED, count); used = atomic_add_return(count, &q->nr_buf_used); BUG_ON(used > QDIO_MAX_BUFFERS_PER_Q); - if (callflags & QDIO_FLAG_PCI_OUT) + if (callflags & QDIO_FLAG_PCI_OUT) { q->u.out.pci_out_enabled = 1; + qperf_inc(q, pci_request_int); + } else q->u.out.pci_out_enabled = 0; @@ -1484,7 +1485,7 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, if (state != SLSB_CU_OUTPUT_PRIMED) rc = qdio_kick_outbound_q(q); else - qdio_perf_stat_inc(&perf_stats.fast_requeue); + qperf_inc(q, fast_requeue); out: tasklet_schedule(&q->tasklet); @@ -1540,16 +1541,11 @@ static int __init init_QDIO(void) rc = qdio_debug_init(); if (rc) goto out_ti; - rc = qdio_setup_perf_stats(); - if (rc) - goto out_debug; rc = tiqdio_register_thinints(); if (rc) - goto out_perf; + goto out_debug; return 0; -out_perf: - qdio_remove_perf_stats(); out_debug: qdio_debug_exit(); out_ti: @@ -1563,7 +1559,6 @@ static void __exit exit_QDIO(void) { tiqdio_unregister_thinints(); tiqdio_free_memory(); - qdio_remove_perf_stats(); qdio_debug_exit(); qdio_setup_exit(); } diff --git a/drivers/s390/cio/qdio_perf.c b/drivers/s390/cio/qdio_perf.c deleted file mode 100644 index 54f7c325a3e..00000000000 --- a/drivers/s390/cio/qdio_perf.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * drivers/s390/cio/qdio_perf.c - * - * Copyright IBM Corp. 2008 - * - * Author: Jan Glauber (jang@linux.vnet.ibm.com) - */ -#include -#include -#include -#include - -#include "cio.h" -#include "css.h" -#include "device.h" -#include "ioasm.h" -#include "chsc.h" -#include "qdio_debug.h" -#include "qdio_perf.h" - -int qdio_performance_stats; -struct qdio_perf_stats perf_stats; - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *qdio_perf_pde; -#endif - -/* - * procfs functions - */ -static int qdio_perf_proc_show(struct seq_file *m, void *v) -{ - seq_printf(m, "Number of qdio interrupts\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.qdio_int)); - seq_printf(m, "Number of PCI interrupts\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.pci_int)); - seq_printf(m, "Number of adapter interrupts\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.thin_int)); - seq_printf(m, "\n"); - seq_printf(m, "Inbound tasklet runs\t\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.tasklet_inbound)); - seq_printf(m, "Outbound tasklet runs\t\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.tasklet_outbound)); - seq_printf(m, "Adapter interrupt tasklet runs/loops\t\t: %li/%li\n", - (long)atomic_long_read(&perf_stats.tasklet_thinint), - (long)atomic_long_read(&perf_stats.tasklet_thinint_loop)); - seq_printf(m, "Adapter interrupt inbound tasklet runs/loops\t: %li/%li\n", - (long)atomic_long_read(&perf_stats.thinint_inbound), - (long)atomic_long_read(&perf_stats.thinint_inbound_loop)); - seq_printf(m, "\n"); - seq_printf(m, "Number of SIGA In issued\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.siga_in)); - seq_printf(m, "Number of SIGA Out issued\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.siga_out)); - seq_printf(m, "Number of SIGA Sync issued\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.siga_sync)); - seq_printf(m, "\n"); - seq_printf(m, "Number of inbound transfers\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.inbound_handler)); - seq_printf(m, "Number of outbound transfers\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.outbound_handler)); - seq_printf(m, "\n"); - seq_printf(m, "Number of fast requeues (outg. SBAL w/o SIGA)\t: %li\n", - (long)atomic_long_read(&perf_stats.fast_requeue)); - seq_printf(m, "Number of outbound target full condition\t: %li\n", - (long)atomic_long_read(&perf_stats.outbound_target_full)); - seq_printf(m, "Number of inbound queue full condition\t\t: %li\n", - (long)atomic_long_read(&perf_stats.inbound_queue_full)); - seq_printf(m, "Number of outbound tasklet mod_timer calls\t: %li\n", - (long)atomic_long_read(&perf_stats.debug_tl_out_timer)); - seq_printf(m, "Number of stop polling calls\t\t\t: %li\n", - (long)atomic_long_read(&perf_stats.debug_stop_polling)); - seq_printf(m, "AI inbound tasklet loops after stop polling\t: %li\n", - (long)atomic_long_read(&perf_stats.thinint_inbound_loop2)); - seq_printf(m, "QEBSM EQBS total/incomplete\t\t\t: %li/%li\n", - (long)atomic_long_read(&perf_stats.debug_eqbs_all), - (long)atomic_long_read(&perf_stats.debug_eqbs_incomplete)); - seq_printf(m, "QEBSM SQBS total/incomplete\t\t\t: %li/%li\n", - (long)atomic_long_read(&perf_stats.debug_sqbs_all), - (long)atomic_long_read(&perf_stats.debug_sqbs_incomplete)); - seq_printf(m, "\n"); - return 0; -} -static int qdio_perf_seq_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, qdio_perf_proc_show, NULL); -} - -static const struct file_operations qdio_perf_proc_fops = { - .owner = THIS_MODULE, - .open = qdio_perf_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * sysfs functions - */ -static ssize_t qdio_perf_stats_show(struct bus_type *bus, char *buf) -{ - return sprintf(buf, "%i\n", qdio_performance_stats ? 1 : 0); -} - -static ssize_t qdio_perf_stats_store(struct bus_type *bus, - const char *buf, size_t count) -{ - unsigned long i; - - if (strict_strtoul(buf, 16, &i) != 0) - return -EINVAL; - if ((i != 0) && (i != 1)) - return -EINVAL; - if (i == qdio_performance_stats) - return count; - - qdio_performance_stats = i; - /* reset performance statistics */ - if (i == 0) - memset(&perf_stats, 0, sizeof(struct qdio_perf_stats)); - return count; -} - -static BUS_ATTR(qdio_performance_stats, 0644, qdio_perf_stats_show, - qdio_perf_stats_store); - -int __init qdio_setup_perf_stats(void) -{ - int rc; - - rc = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); - if (rc) - return rc; - -#ifdef CONFIG_PROC_FS - memset(&perf_stats, 0, sizeof(struct qdio_perf_stats)); - qdio_perf_pde = proc_create("qdio_perf", S_IFREG | S_IRUGO, - NULL, &qdio_perf_proc_fops); -#endif - return 0; -} - -void qdio_remove_perf_stats(void) -{ -#ifdef CONFIG_PROC_FS - remove_proc_entry("qdio_perf", NULL); -#endif - bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); -} diff --git a/drivers/s390/cio/qdio_perf.h b/drivers/s390/cio/qdio_perf.h deleted file mode 100644 index 12454231dc8..00000000000 --- a/drivers/s390/cio/qdio_perf.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * drivers/s390/cio/qdio_perf.h - * - * Copyright IBM Corp. 2008 - * - * Author: Jan Glauber (jang@linux.vnet.ibm.com) - */ -#ifndef QDIO_PERF_H -#define QDIO_PERF_H - -#include -#include - -struct qdio_perf_stats { - /* interrupt handler calls */ - atomic_long_t qdio_int; - atomic_long_t pci_int; - atomic_long_t thin_int; - - /* tasklet runs */ - atomic_long_t tasklet_inbound; - atomic_long_t tasklet_outbound; - atomic_long_t tasklet_thinint; - atomic_long_t tasklet_thinint_loop; - atomic_long_t thinint_inbound; - atomic_long_t thinint_inbound_loop; - atomic_long_t thinint_inbound_loop2; - - /* signal adapter calls */ - atomic_long_t siga_out; - atomic_long_t siga_in; - atomic_long_t siga_sync; - - /* misc */ - atomic_long_t inbound_handler; - atomic_long_t outbound_handler; - atomic_long_t fast_requeue; - atomic_long_t outbound_target_full; - atomic_long_t inbound_queue_full; - - /* for debugging */ - atomic_long_t debug_tl_out_timer; - atomic_long_t debug_stop_polling; - atomic_long_t debug_eqbs_all; - atomic_long_t debug_eqbs_incomplete; - atomic_long_t debug_sqbs_all; - atomic_long_t debug_sqbs_incomplete; -}; - -extern struct qdio_perf_stats perf_stats; -extern int qdio_performance_stats; - -static inline void qdio_perf_stat_inc(atomic_long_t *count) -{ - if (qdio_performance_stats) - atomic_long_inc(count); -} - -int qdio_setup_perf_stats(void); -void qdio_remove_perf_stats(void); - -#endif diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 981a77ea7ee..091d904d318 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -1,9 +1,7 @@ /* * linux/drivers/s390/cio/thinint_qdio.c * - * thin interrupt support for qdio - * - * Copyright 2000-2008 IBM Corp. + * Copyright 2000,2009 IBM Corp. * Author(s): Utz Bacher * Cornelia Huck * Jan Glauber @@ -19,7 +17,6 @@ #include "ioasm.h" #include "qdio.h" #include "qdio_debug.h" -#include "qdio_perf.h" /* * Restriction: only 63 iqdio subchannels would have its own indicator, @@ -132,8 +129,6 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) { struct qdio_q *q; - qdio_perf_stat_inc(&perf_stats.thin_int); - /* * SVS only when needed: issue SVS to benefit from iqdio interrupt * avoidance (SVS clears adapter interrupt suppression overwrite) @@ -154,6 +149,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) list_for_each_entry_rcu(q, &tiq_list, entry) /* only process queues from changed sets */ if (*q->irq_ptr->dsci) { + qperf_inc(q, adapter_int); /* only clear it if the indicator is non-shared */ if (!shared_ind(q->irq_ptr)) -- cgit v1.2.3 From 2d1ee87d8763b38668f6f11bb53abb689a49a43e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 27 Dec 2009 22:27:11 +0100 Subject: drivers/block/drbd: Correct NULL test Test the just-allocated value for NULL rather than some other value. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,y; statement S; @@ x = \(kmalloc\|kcalloc\|kzalloc\)(...); ( if ((x) == NULL) S | if ( - y + x == NULL) S ) // Signed-off-by: Julia Lawall Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a6d266ee7e2..dbd451984e0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3945,7 +3945,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) } right_response = kmalloc(resp_size, GFP_NOIO); - if (response == NULL) { + if (right_response == NULL) { dev_err(DEV, "kmalloc of right_response failed\n"); rv = 0; goto fail; -- cgit v1.2.3 From 40da4186a53e59d801130156ecb89fc5830ff227 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Tue, 15 Dec 2009 11:38:04 +0900 Subject: PCI: pcie portdrv: style cleanup No change in logic. Before: drivers/pci/pcie/portdrv_core.c: total: 7 errors, 2 warnings, 508 lines checked drivers/pci/pcie/portdrv_pci.c: total: 4 errors, 2 warnings, 300 lines checked After: drivers/pci/pcie/portdrv_core.c: total: 0 errors, 0 warnings, 506 lines checked drivers/pci/pcie/portdrv_pci.c: total: 0 errors, 0 warnings, 299 lines checked Signed-off-by: Hidetoshi Seto Signed-off-by: Jesse Barnes --- drivers/pci/pcie/portdrv_core.c | 16 +++++++--------- drivers/pci/pcie/portdrv_pci.c | 17 ++++++++--------- 2 files changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 413262eb95b..b174188ac12 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -27,7 +27,7 @@ */ static void release_pcie_device(struct device *dev) { - kfree(to_pcie_device(dev)); + kfree(to_pcie_device(dev)); } /** @@ -346,12 +346,11 @@ static int suspend_iter(struct device *dev, void *data) { struct pcie_port_service_driver *service_driver; - if ((dev->bus == &pcie_port_bus_type) && - (dev->driver)) { - service_driver = to_service_driver(dev->driver); - if (service_driver->suspend) - service_driver->suspend(to_pcie_device(dev)); - } + if ((dev->bus == &pcie_port_bus_type) && dev->driver) { + service_driver = to_service_driver(dev->driver); + if (service_driver->suspend) + service_driver->suspend(to_pcie_device(dev)); + } return 0; } @@ -494,6 +493,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new) return driver_register(&new->driver); } +EXPORT_SYMBOL(pcie_port_service_register); /** * pcie_port_service_unregister - unregister PCI Express port service driver @@ -503,6 +503,4 @@ void pcie_port_service_unregister(struct pcie_port_service_driver *drv) { driver_unregister(&drv->driver); } - -EXPORT_SYMBOL(pcie_port_service_register); EXPORT_SYMBOL(pcie_port_service_unregister); diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 34d65172a4d..13c8972886e 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -63,7 +63,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { * pcie_portdrv_probe - Probe PCI-Express port devices * @dev: PCI-Express port device being probed * - * If detected invokes the pcie_port_device_register() method for + * If detected invokes the pcie_port_device_register() method for * this port device. * */ @@ -78,7 +78,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) return -ENODEV; - if (!dev->irq && dev->pin) { + if (!dev->irq && dev->pin) { dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " "check vendor BIOS\n", dev->vendor, dev->device); } @@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, return 0; } -static void pcie_portdrv_remove (struct pci_dev *dev) +static void pcie_portdrv_remove(struct pci_dev *dev) { pcie_port_device_remove(dev); pci_disable_device(dev); @@ -129,14 +129,13 @@ static int error_detected_iter(struct device *device, void *data) static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, enum pci_channel_state error) { - struct aer_broadcast_data result_data = - {error, PCI_ERS_RESULT_CAN_RECOVER}; - int retval; + struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER}; + int ret; /* can not fail */ - retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter); + ret = device_for_each_child(&dev->dev, &data, error_detected_iter); - return result_data.result; + return data.result; } static int mmio_enabled_iter(struct device *device, void *data) @@ -290,7 +289,7 @@ static int __init pcie_portdrv_init(void) return retval; } -static void __exit pcie_portdrv_exit(void) +static void __exit pcie_portdrv_exit(void) { pci_unregister_driver(&pcie_portdriver); pcie_port_bus_unregister(); -- cgit v1.2.3 From 46256f83d0d066f99ffde547f27473dfd2a78009 Mon Sep 17 00:00:00 2001 From: "Youquan,Song" Date: Fri, 11 Dec 2009 18:42:35 -0500 Subject: PCI: AER: fix aer inject result in kernel oops If the BIOS does not export _OSC to allow OS take over the PCIe AER, the pcie aer driver will not initialize the aer service. However, the aer_inject driver does not check this scenario, which results in a kernel oops when injecting an aer error into OS. For example: BUG: unable to handle kernel NULL pointer dereference at 0000000000000350 IP: [] _spin_lock_irqsave+0xc/0x23 PGD 155c41067 PUD 157fe0067 PMD 0 Oops: 0002 [#1] SMP Pid: 5119, comm: aer-inject Not tainted 2.6.32-rc8-mce #2 RIP: 0010:[] [] _spin_lock_irqsave+0xc/0x23 RSP: 0018:ffff880157f81e28 EFLAGS: 00010096 RAX: 0000000000000296 RBX: 0000000000000000 RCX: 0000000000000100 RDX: 0000000000010000 RSI: 0000000000000246 RDI: 0000000000000350 RBP: ffff880157f81e28 R08: 0000000000000004 R09: ffff880157f81dac R10: ffff88015a666f60 R11: ffff88015a666f40 R12: ffff88015758cc00 R13: 0000000000000350 R14: 0000000000000000 R15: 0000000000000100 FS: 00007f4d4a66e6f0(0000) GS:ffff8800282e0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000350 CR3: 000000015661a000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process aer-inject (pid: 5119, threadinfo ffff880157f80000, task ffff8801585f4340) Stack: ffff880157f81e78 ffffffff811b1615 ffff880157f81e78 ffffffff81222823 Call Trace: [] aer_irq+0x38/0x117 [] ? device_for_each_child+0x5f/0x6f [] aer_inject_write+0x409/0x45e [aer_inject] [] vfs_write+0xae/0x16a [] sys_write+0x47/0x6e [] system_call_fastpath+0x16/0x1b RIP [] _spin_lock_irqsave+0xc/0x23 RSP CR2: 0000000000000350 So check the _OSC before assuming that AER is available to the OS. Signed-off-by: Youquan, Song Acked-by: Ying, Huang Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aer_inject.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 797d47809f7..dd7155a037e 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -413,8 +413,14 @@ static int aer_inject(struct aer_error_inj *einj) if (ret) goto out_put; - if (find_aer_device(rpdev, &edev)) + if (find_aer_device(rpdev, &edev)) { + if (!get_service_data(edev)) { + printk(KERN_WARNING "AER service is not initialized\n"); + ret = -EINVAL; + goto out_put; + } aer_irq(-1, edev); + } else ret = -EINVAL; out_put: -- cgit v1.2.3 From 91e6ecada757a6e2ef7b937634af8a04376772a1 Mon Sep 17 00:00:00 2001 From: Ed Lin Date: Fri, 18 Dec 2009 17:34:51 -0800 Subject: [SCSI] stex: fix scan of nonexistent lun During a manual scan, a user can send command to a nonexistent lun, precisely at the point of max_lun. Normally it's possible (but not required) that the firmware has the knowledge that it is an invalid lun. In the particular case when max_lun is 256, however, the nonexistent lun 256 will be confused with lun 0, because the lun member in a request message is only u8, and 256 will become 0. So we need to fix the problem, at least, at the driver level. Signed-off-by: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 3058bb1aff9..fd7b15be764 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -623,6 +623,11 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) } break; case INQUIRY: + if (lun >= host->max_lun) { + cmd->result = DID_NO_CONNECT << 16; + done(cmd); + return 0; + } if (id != host->max_id - 1) break; if (!lun && !cmd->device->channel && -- cgit v1.2.3 From eeead8115276a76675dc7cfc823a2461745edd27 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 21 Dec 2009 17:01:23 -0500 Subject: [SCSI] lpfc 8.3.7: Fix FC protocol errors Fix FC protocol errors: - Fix multi-frame unsolicited sequences not queued properly - Fix frames for unsolicited sequences not being associated with sequence. - Fix unsolicited frame buffer sizes are not set properly - Fix Sequence count for unsolicited frame headers not byte swapped. - Fix Multi-frame sequence response frames go to wrong DID. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hw4.h | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 1585148a17e..09c8e362aee 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1013,7 +1013,7 @@ struct lpfc_mbx_wq_destroy { }; #define LPFC_HDR_BUF_SIZE 128 -#define LPFC_DATA_BUF_SIZE 4096 +#define LPFC_DATA_BUF_SIZE 2048 struct rq_context { uint32_t word0; #define lpfc_rq_context_rq_size_SHIFT 16 diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7935667b81a..50f72bf1825 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5848,7 +5848,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, iocbq->iocb.un.ulpWord[3]); wqe->generic.word3 = 0; bf_set(wqe_rcvoxid, &wqe->generic, iocbq->iocb.ulpContext); - bf_set(wqe_xc, &wqe->generic, 1); /* The entire sequence is transmitted for this IOCB */ xmit_len = total_len; cmnd = CMD_XMIT_SEQUENCE64_CR; @@ -10944,7 +10943,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) return dmabuf; } temp_hdr = seq_dmabuf->hbuf.virt; - if (new_hdr->fh_seq_cnt < temp_hdr->fh_seq_cnt) { + if (be16_to_cpu(new_hdr->fh_seq_cnt) < + be16_to_cpu(temp_hdr->fh_seq_cnt)) { list_del_init(&seq_dmabuf->hbuf.list); list_add_tail(&dmabuf->hbuf.list, &vport->rcv_buffer_list); list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list); @@ -10955,6 +10955,11 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) list_move_tail(&seq_dmabuf->hbuf.list, &vport->rcv_buffer_list); seq_dmabuf->time_stamp = jiffies; lpfc_update_rcv_time_stamp(vport); + if (list_empty(&seq_dmabuf->dbuf.list)) { + temp_hdr = dmabuf->hbuf.virt; + list_add_tail(&dmabuf->dbuf.list, &seq_dmabuf->dbuf.list); + return seq_dmabuf; + } /* find the correct place in the sequence to insert this frame */ list_for_each_entry_reverse(d_buf, &seq_dmabuf->dbuf.list, list) { temp_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf); @@ -10963,7 +10968,8 @@ lpfc_fc_frame_add(struct lpfc_vport *vport, struct hbq_dmabuf *dmabuf) * If the frame's sequence count is greater than the frame on * the list then insert the frame right after this frame */ - if (new_hdr->fh_seq_cnt > temp_hdr->fh_seq_cnt) { + if (be16_to_cpu(new_hdr->fh_seq_cnt) > + be16_to_cpu(temp_hdr->fh_seq_cnt)) { list_add(&dmabuf->dbuf.list, &temp_dmabuf->dbuf.list); return seq_dmabuf; } @@ -11210,7 +11216,7 @@ lpfc_seq_complete(struct hbq_dmabuf *dmabuf) seq_dmabuf = container_of(d_buf, struct hbq_dmabuf, dbuf); hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; /* If there is a hole in the sequence count then fail. */ - if (++seq_count != hdr->fh_seq_cnt) + if (++seq_count != be16_to_cpu(hdr->fh_seq_cnt)) return 0; fctl = (hdr->fh_f_ctl[0] << 16 | hdr->fh_f_ctl[1] << 8 | @@ -11242,6 +11248,7 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) struct lpfc_iocbq *first_iocbq, *iocbq; struct fc_frame_header *fc_hdr; uint32_t sid; + struct ulp_bde64 *pbde; fc_hdr = (struct fc_frame_header *)seq_dmabuf->hbuf.virt; /* remove from receive buffer list */ @@ -11283,8 +11290,9 @@ lpfc_prep_seq(struct lpfc_vport *vport, struct hbq_dmabuf *seq_dmabuf) if (!iocbq->context3) { iocbq->context3 = d_buf; iocbq->iocb.ulpBdeCount++; - iocbq->iocb.unsli3.rcvsli3.bde2.tus.f.bdeSize = - LPFC_DATA_BUF_SIZE; + pbde = (struct ulp_bde64 *) + &iocbq->iocb.unsli3.sli3Words[4]; + pbde->tus.f.bdeSize = LPFC_DATA_BUF_SIZE; first_iocbq->iocb.unsli3.rcvsli3.acc_len += bf_get(lpfc_rcqe_length, &seq_dmabuf->cq_event.cqe.rcqe_cmpl); @@ -11407,7 +11415,6 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, * frame to be freed when it is finished. **/ lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1); - dmabuf->tag = -1; return; } /* Send the complete sequence to the upper layer protocol */ -- cgit v1.2.3 From 1987807d4a7f52ca86034865283b207ab9be79c8 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 21 Dec 2009 17:02:00 -0500 Subject: [SCSI] lpfc 8.3.7: Fix NPIV operation errors Fix NPIV operation errors: - Fix vport not logging out of fabric when being deleted - Fix vport fails to discover targets after devloss timeout. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 1 + drivers/scsi/lpfc/lpfc_vport.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index ce522702a6c..bb2e43a9e96 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -5948,8 +5948,8 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_initial_fdisc(vport); break; } - } else { + vport->vpi_state |= LPFC_VPI_REGISTERED; if (vport == phba->pport) if (phba->sli_rev < LPFC_SLI_REV4) lpfc_issue_fabric_reglogin(vport); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 3b942442765..401167de4ff 100755 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -2260,6 +2260,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) break; } vport->vpi_state &= ~LPFC_VPI_REGISTERED; + vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; vport->unreg_vpi_cmpl = VPORT_OK; mempool_free(pmb, phba->mbox_mem_pool); /* diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 7d6dd83d359..c3a70c4c943 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -700,7 +700,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) } spin_unlock_irq(&phba->ndlp_lock); } - if (vport->vpi_state != LPFC_VPI_REGISTERED) + if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) goto skip_logo; vport->unreg_vpi_cmpl = VPORT_INVAL; timeout = msecs_to_jiffies(phba->fc_ratov * 2000); -- cgit v1.2.3 From def9c7a994f194377a23e687e6fd39b46c3ce631 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 21 Dec 2009 17:02:28 -0500 Subject: [SCSI] lpfc 8.3.7: Fix hardware/SLI relates issues Fix hardware/SLI relates issues: - Fix CNA uses more than one EQ when in INTx interrupt mode. - Fix driver tries to process failed read FCF record mailbox request. - Fix allocating single receive buffer breaks FCoE receive queue. - Support new read FCF record mailbox error case. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 14 ++++++++++---- drivers/scsi/lpfc/lpfc_hw4.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 3 +++ drivers/scsi/lpfc/lpfc_sli.c | 27 +++++++++++++++------------ drivers/scsi/lpfc/lpfc_sli4.h | 2 +- 5 files changed, 30 insertions(+), 17 deletions(-) mode change 100644 => 100755 drivers/scsi/lpfc/lpfc_hw4.h (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 401167de4ff..f40b9609f6e 100755 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1555,10 +1555,16 @@ lpfc_mbx_cmpl_read_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) * to book keeping the FCFIs can be used. */ if (shdr_status || shdr_add_status) { - lpfc_printf_log(phba, KERN_ERR, LOG_INIT, - "2521 READ_FCF_RECORD mailbox failed " - "with status x%x add_status x%x, mbx\n", - shdr_status, shdr_add_status); + if (shdr_status == STATUS_FCF_TABLE_EMPTY) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2726 READ_FCF_RECORD Indicates empty " + "FCF table.\n"); + } else { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2521 READ_FCF_RECORD mailbox failed " + "with status x%x add_status x%x, mbx\n", + shdr_status, shdr_add_status); + } goto out; } /* Interpreting the returned information of FCF records */ diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h old mode 100644 new mode 100755 index 09c8e362aee..8a2a1c5935c --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1371,6 +1371,7 @@ struct lpfc_mbx_query_fw_cfg { #define STATUS_ERROR_ACITMAIN 0x2a #define STATUS_REBOOT_REQUIRED 0x2c #define STATUS_FCF_IN_USE 0x3a +#define STATUS_FCF_TABLE_EMPTY 0x43 struct lpfc_mbx_sli4_config { struct mbox_header header; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index d4da6bdd0e7..7083ef3b387 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7507,6 +7507,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid) error = -ENODEV; goto out_free_sysfs_attr; } + /* Default to single FCP EQ for non-MSI-X */ + if (phba->intr_type != MSIX) + phba->cfg_fcp_eq_count = 1; /* Set up SLI-4 HBA */ if (lpfc_sli4_hba_setup(phba)) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 50f72bf1825..589549b2bf0 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1383,7 +1383,7 @@ lpfc_sli_hbq_to_firmware_s4(struct lpfc_hba *phba, uint32_t hbqno, /* HBQ for ELS and CT traffic. */ static struct lpfc_hbq_init lpfc_els_hbq = { .rn = 1, - .entry_count = 200, + .entry_count = 256, .mask_count = 0, .profile = 0, .ring_mask = (1 << LPFC_ELS_RING), @@ -1482,8 +1482,11 @@ err: int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno) { - return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno, - lpfc_hbq_defs[qno]->add_count)); + if (phba->sli_rev == LPFC_SLI_REV4) + return 0; + else + return lpfc_sli_hbqbuf_fill_hbqs(phba, qno, + lpfc_hbq_defs[qno]->add_count); } /** @@ -1498,8 +1501,12 @@ lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *phba, uint32_t qno) static int lpfc_sli_hbqbuf_init_hbqs(struct lpfc_hba *phba, uint32_t qno) { - return(lpfc_sli_hbqbuf_fill_hbqs(phba, qno, - lpfc_hbq_defs[qno]->init_count)); + if (phba->sli_rev == LPFC_SLI_REV4) + return lpfc_sli_hbqbuf_fill_hbqs(phba, qno, + lpfc_hbq_defs[qno]->entry_count); + else + return lpfc_sli_hbqbuf_fill_hbqs(phba, qno, + lpfc_hbq_defs[qno]->init_count); } /** @@ -4110,6 +4117,7 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq, if (rc) { dma_free_coherent(&phba->pcidev->dev, dma_size, dmabuf->virt, dmabuf->phys); + kfree(dmabuf); return -EIO; } @@ -11409,14 +11417,9 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba, return; } /* If not last frame in sequence continue processing frames. */ - if (!lpfc_seq_complete(seq_dmabuf)) { - /* - * When saving off frames post a new one and mark this - * frame to be freed when it is finished. - **/ - lpfc_sli_hbqbuf_fill_hbqs(phba, LPFC_ELS_HBQ, 1); + if (!lpfc_seq_complete(seq_dmabuf)) return; - } + /* Send the complete sequence to the upper layer protocol */ lpfc_sli4_send_seq_to_ulp(vport, seq_dmabuf); } diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 25d66d070cf..44e5f574236 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -28,7 +28,7 @@ /* Multi-queue arrangement for fast-path FCP work queues */ #define LPFC_FN_EQN_MAX 8 #define LPFC_SP_EQN_DEF 1 -#define LPFC_FP_EQN_DEF 1 +#define LPFC_FP_EQN_DEF 4 #define LPFC_FP_EQN_MIN 1 #define LPFC_FP_EQN_MAX (LPFC_FN_EQN_MAX - LPFC_SP_EQN_DEF) -- cgit v1.2.3 From aacc20e35edfb86cf66c5ee8d9f3d06a98362fd1 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 21 Dec 2009 17:02:51 -0500 Subject: [SCSI] lpfc 8.3.7: Fix SCSI protocol related errors. Fix SCSI protocol related errors: - Avoid I/O failures during EEH and HBA/CNA reset by correcting when we block the targets on the adapter. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_hbadisc.c | 4 ++++ drivers/scsi/lpfc/lpfc_init.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index f40b9609f6e..1c2737293eb 100755 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -747,6 +747,10 @@ lpfc_linkdown(struct lpfc_hba *phba) if (phba->link_state == LPFC_LINK_DOWN) return 0; + + /* Block all SCSI stack I/Os */ + lpfc_scsi_dev_block(phba); + spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~(FCF_AVAILABLE | FCF_DISCOVERED); if (phba->link_state > LPFC_LINK_DOWN) { diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7083ef3b387..974ea6d85ef 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7226,8 +7226,6 @@ lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "2711 PCI channel permanent disable for failure\n"); - /* Block all SCSI devices' I/Os on the host */ - lpfc_scsi_dev_block(phba); /* Clean up all driver's outstanding SCSI I/Os */ lpfc_sli_flush_fcp_rings(phba); } @@ -7256,6 +7254,9 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state) struct Scsi_Host *shost = pci_get_drvdata(pdev); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; + /* Block all SCSI devices' I/Os on the host */ + lpfc_scsi_dev_block(phba); + switch (state) { case pci_channel_io_normal: /* Non-fatal error, prepare for recovery */ -- cgit v1.2.3 From 9795724476860069ce183ead59d0a5958f882037 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 21 Dec 2009 17:03:15 -0500 Subject: [SCSI] lpfc 8.3.7: Fix discovery failures. Fix discovery failures: - Move all accesses to the fc_flag field inside the host lock. - Restore link state after going through linkdown processing for FCF DEAD event. Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 6 ++++++ drivers/scsi/lpfc/lpfc_init.c | 6 +++++- drivers/scsi/lpfc/lpfc_vport.c | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index bb2e43a9e96..2cc39684ce9 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -4142,8 +4142,8 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, spin_lock_irq(shost->host_lock); if (vport->fc_rscn_flush) { /* Another thread is walking fc_rscn_id_list on this vport */ - spin_unlock_irq(shost->host_lock); vport->fc_flag |= FC_RSCN_DISCOVERY; + spin_unlock_irq(shost->host_lock); /* Send back ACC */ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); return 0; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 1c2737293eb..2445e399fd6 100755 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1708,7 +1708,9 @@ lpfc_init_vpi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) lpfc_vport_set_state(vport, FC_VPORT_FAILED); return; } + spin_lock_irq(&phba->hbalock); vport->fc_flag &= ~FC_VPORT_NEEDS_INIT_VPI; + spin_unlock_irq(&phba->hbalock); if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) lpfc_initial_fdisc(vport); @@ -2269,8 +2271,10 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mb->mbxStatus); break; } + spin_lock_irq(&phba->hbalock); vport->vpi_state &= ~LPFC_VPI_REGISTERED; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + spin_unlock_irq(&phba->hbalock); vport->unreg_vpi_cmpl = VPORT_OK; mempool_free(pmb, phba->mbox_mem_pool); /* @@ -4486,8 +4490,10 @@ lpfc_unregister_unused_fcf(struct lpfc_hba *phba) (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { lpfc_mbx_unreg_vpi(vports[i]); + spin_lock_irq(&phba->hbalock); vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED; + spin_unlock_irq(&phba->hbalock); } lpfc_destroy_vport_work_array(phba, vports); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 974ea6d85ef..b8eb1b6e5e7 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3006,6 +3006,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, struct lpfc_vport *vport; struct lpfc_nodelist *ndlp; struct Scsi_Host *shost; + uint32_t link_state; phba->fc_eventTag = acqe_fcoe->event_tag; phba->fcoe_eventtag = acqe_fcoe->event_tag; @@ -3052,9 +3053,12 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, break; /* * Currently, driver support only one FCF - so treat this as - * a link down. + * a link down, but save the link state because we don't want + * it to be changed to Link Down unless it is already down. */ + link_state = phba->link_state; lpfc_linkdown(phba); + phba->link_state = link_state; /* Unregister FCF if no devices connected to it */ lpfc_unregister_unused_fcf(phba); break; diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index c3a70c4c943..e3c7fa64230 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -512,8 +512,10 @@ enable_vport(struct fc_vport *fc_vport) return VPORT_OK; } + spin_lock_irq(&phba->hbalock); vport->load_flag |= FC_LOADING; vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI; + spin_unlock_irq(&phba->hbalock); /* Use the Physical nodes Fabric NDLP to determine if the link is * up and ready to FDISC. -- cgit v1.2.3 From 500af638b3f378e5d1f04dfe5043a377cdc234de Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 21 Dec 2009 17:03:47 -0500 Subject: [SCSI] lpfc 8.3.7: Update Driver version to 8.3.7 Update Driver version to 8.3.7 Signed-off-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c7f3aed2aab..792f72263f1 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.6" +#define LPFC_DRIVER_VERSION "8.3.7" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" -- cgit v1.2.3 From 6432e734c99ed685e3cad72f7dcae4c65008fcab Mon Sep 17 00:00:00 2001 From: John Kacur Date: Sun, 18 Oct 2009 23:49:49 +0200 Subject: sony_pi: Remove the BKL from open and ioctl The BKL is in this function because of the BKL pushdown (see commit f8f2c79d594463427f7114cedb1555110d547d89) It is not needed here because the mutex_lock sonypi_device.lock provides the necessary locking. sonypi_misc_ioctl can be converted to unlocked ioctls since it relies on its own locking (the mutex sonypi_device.lock) and not the bkl Document that llseek is not needed by explictly setting it to no_llseek LKML-Reference: Signed-off-by: John Kacur Acked-by: Arnd Bergmann Signed-off-by: Linus Torvalds --- drivers/char/sonypi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 0798754a607..bba727c3807 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include @@ -905,14 +904,13 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { - lock_kernel(); mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) kfifo_reset(&sonypi_device.fifo); sonypi_device.open_count++; mutex_unlock(&sonypi_device.lock); - unlock_kernel(); + return 0; } @@ -955,10 +953,10 @@ static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) return 0; } -static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, +static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { - int ret = 0; + long ret = 0; void __user *argp = (void __user *)arg; u8 val8; u16 val16; @@ -1074,7 +1072,8 @@ static const struct file_operations sonypi_misc_fops = { .open = sonypi_misc_open, .release = sonypi_misc_release, .fasync = sonypi_misc_fasync, - .ioctl = sonypi_misc_ioctl, + .unlocked_ioctl = sonypi_misc_ioctl, + .llseek = no_llseek, }; static struct miscdevice sonypi_misc_device = { -- cgit v1.2.3 From 5d9d6e44ce15d072d22c10fe670679c77fa2b31d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:18:27 +0000 Subject: i2o: propogate the BKL down into the ioctl method Nobody seems to want to own I2O patches so sending this one directly. Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/message/i2o/i2o_config.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index efba7021948..3d5f40cd69d 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -40,8 +40,7 @@ #define SG_TABLESIZE 30 -static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); +static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long); static spinlock_t i2o_config_lock; @@ -751,7 +750,7 @@ static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, lock_kernel(); switch (cmd) { case I2OGETIOPS: - ret = i2o_cfg_ioctl(NULL, file, cmd, arg); + ret = i2o_cfg_ioctl(file, cmd, arg); break; case I2OPASSTHRU32: ret = i2o_cfg_passthru32(file, cmd, arg); @@ -984,11 +983,11 @@ out: /* * IOCTL Handler */ -static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, - unsigned long arg) +static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { int ret; + lock_kernel(); switch (cmd) { case I2OGETIOPS: ret = i2o_cfg_getiops(arg); @@ -1044,7 +1043,7 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, osm_debug("unknown ioctl called!\n"); ret = -EINVAL; } - + unlock_kernel(); return ret; } @@ -1118,7 +1117,7 @@ static int cfg_release(struct inode *inode, struct file *file) static const struct file_operations config_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .ioctl = i2o_cfg_ioctl, + .unlocked_ioctl = i2o_cfg_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = i2o_cfg_compat_ioctl, #endif -- cgit v1.2.3 From 3e8d95d95eaf4b332f6e1862ffbaa80c24780767 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:19:55 +0000 Subject: tosh: Use non bkl ioctl We wrap the smm calls and other bits with the BKL push down as a precaution but they can probably go Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/toshiba.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 663cd15d7c7..f8bc79f6de3 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -68,7 +68,7 @@ #include #include #include - +#include #include #define TOSH_MINOR_DEV 181 @@ -88,13 +88,13 @@ static int tosh_date; static int tosh_sci; static int tosh_fan; -static int tosh_ioctl(struct inode *, struct file *, unsigned int, +static long tosh_ioctl(struct file *, unsigned int, unsigned long); static const struct file_operations tosh_fops = { .owner = THIS_MODULE, - .ioctl = tosh_ioctl, + .unlocked_ioctl = tosh_ioctl, }; static struct miscdevice tosh_device = { @@ -252,8 +252,7 @@ int tosh_smm(SMMRegisters *regs) EXPORT_SYMBOL(tosh_smm); -static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) +static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { SMMRegisters regs; SMMRegisters __user *argp = (SMMRegisters __user *)arg; @@ -275,13 +274,16 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -EINVAL; /* do we need to emulate the fan ? */ + lock_kernel(); if (tosh_fan==1) { if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) { err = tosh_emulate_fan(®s); + unlock_kernel(); break; } } err = tosh_smm(®s); + unlock_kernel(); break; default: return -EINVAL; -- cgit v1.2.3 From 3e27249c84beed1c79d767b350e52ad038db9053 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 4 Jan 2010 19:26:14 +1030 Subject: lguest: fix bug in setting guest GDT entry We kill the guest, but then we blatt random stuff. Reported-by: Dan Carpenter Signed-off-by: Rusty Russell Cc: stable@kernel.org Signed-off-by: Linus Torvalds --- drivers/lguest/segments.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index 951c57b0a7e..ede46581351 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c @@ -179,8 +179,10 @@ void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi) * We assume the Guest has the same number of GDT entries as the * Host, otherwise we'd have to dynamically allocate the Guest GDT. */ - if (num >= ARRAY_SIZE(cpu->arch.gdt)) + if (num >= ARRAY_SIZE(cpu->arch.gdt)) { kill_guest(cpu, "too many gdt entries %i", num); + return; + } /* Set it up, then fix it. */ cpu->arch.gdt[num].a = lo; -- cgit v1.2.3 From 6be954d1f91b81ca85c74792b13654069278c577 Mon Sep 17 00:00:00 2001 From: David John Date: Mon, 4 Jan 2010 20:28:57 +0530 Subject: PCI: Check the node argument passed to cpumask_of_node Commit e0cd516 "PCI: derive nearby CPUs from device's instead of bus' NUMA information" causes an null pointer dereference when reading from the sysfs attributes local_cpu* on Intel machines with no ACPI NUMA proximity info, since dev->numa_node gets set to -1 for all PCI devices, which then gets passed to cpumask_of_node. Add a check to prevent this. Signed-off-by: David John Signed-off-by: Jesse Barnes --- drivers/pci/pci-sysfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c5df94e8667..807224ec835 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -75,7 +75,8 @@ static ssize_t local_cpus_show(struct device *dev, int len; #ifdef CONFIG_NUMA - mask = cpumask_of_node(dev_to_node(dev)); + mask = (dev_to_node(dev) == -1) ? cpu_online_mask : + cpumask_of_node(dev_to_node(dev)); #else mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); #endif @@ -93,7 +94,8 @@ static ssize_t local_cpulist_show(struct device *dev, int len; #ifdef CONFIG_NUMA - mask = cpumask_of_node(dev_to_node(dev)); + mask = (dev_to_node(dev) == -1) ? cpu_online_mask : + cpumask_of_node(dev_to_node(dev)); #else mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); #endif -- cgit v1.2.3 From c7c17c2779075e675cb3c7fe2ecde67e226771fb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 4 Jan 2010 15:31:10 -0800 Subject: bbc_envctrl: Clean up properly if kthread_run() fails. In bbc_envctrl_init() we have to unlink the fan and temp instances from the lists because our caller is going to free up the 'bp' object if we return an error. We can't rely upon bbc_envctrl_cleanup() to do this work for us in this case. Reported-by: Patrick Finnegan Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_envctrl.c | 64 ++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 7c815d3327f..28d86f9df83 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, set_fan_speeds(fp); } +static void destroy_one_temp(struct bbc_cpu_temperature *tp) +{ + bbc_i2c_detach(tp->client); + kfree(tp); +} + +static void destroy_all_temps(struct bbc_i2c_bus *bp) +{ + struct bbc_cpu_temperature *tp, *tpos; + + list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { + list_del(&tp->bp_list); + list_del(&tp->glob_list); + destroy_one_temp(tp); + } +} + +static void destroy_one_fan(struct bbc_fan_control *fp) +{ + bbc_i2c_detach(fp->client); + kfree(fp); +} + +static void destroy_all_fans(struct bbc_i2c_bus *bp) +{ + struct bbc_fan_control *fp, *fpos; + + list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) { + list_del(&fp->bp_list); + list_del(&fp->glob_list); + destroy_one_fan(fp); + } +} + int bbc_envctrl_init(struct bbc_i2c_bus *bp) { struct of_device *op; @@ -541,6 +575,8 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp) int err = PTR_ERR(kenvctrld_task); kenvctrld_task = NULL; + destroy_all_temps(bp); + destroy_all_fans(bp); return err; } } @@ -548,35 +584,11 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp) return 0; } -static void destroy_one_temp(struct bbc_cpu_temperature *tp) -{ - bbc_i2c_detach(tp->client); - kfree(tp); -} - -static void destroy_one_fan(struct bbc_fan_control *fp) -{ - bbc_i2c_detach(fp->client); - kfree(fp); -} - void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) { - struct bbc_cpu_temperature *tp, *tpos; - struct bbc_fan_control *fp, *fpos; - if (kenvctrld_task) kthread_stop(kenvctrld_task); - list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { - list_del(&tp->bp_list); - list_del(&tp->glob_list); - destroy_one_temp(tp); - } - - list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) { - list_del(&fp->bp_list); - list_del(&fp->glob_list); - destroy_one_fan(fp); - } + destroy_all_temps(bp); + destroy_all_fans(bp); } -- cgit v1.2.3 From 1ae861e652b5457e7fa98ccbc55abea1e207916e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 31 Dec 2009 12:15:54 +0100 Subject: PCI/PM: Use per-device D3 delays It turns out that some PCI devices require extra delays when changing power state from D3 to D0 (and the other way around). Although this is against the PCI specification, we can handle it quite easily by allowing drivers to define arbitrary D3 delays for devices known to require extra time for switching power states. Introduce additional field d3_delay in struct pci_dev and use it to store the value of the device's D0->D3 delay, in miliseconds. Make the PCI PM core code use the per-device d3_delay unless pci_pm_d3_delay is greater (in which case the latter is used). [This also allows the driver to specify d3_delay shorter than the 10 ms required by the PCI standard if the device is known to be able to handle that.] Make the sky2 driver set d3_delay to 150 for devices handled by it. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=14730 which is a listed regression from 2.6.30. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jesse Barnes --- drivers/net/sky2.c | 1 + drivers/pci/pci.c | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1c01b96c961..2d28d58200d 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4684,6 +4684,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, INIT_WORK(&hw->restart_work, sky2_restart); pci_set_drvdata(pdev, hw); + pdev->d3_delay = 150; return 0; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0906599ebfd..315fea47e78 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -29,7 +29,17 @@ const char *pci_power_names[] = { }; EXPORT_SYMBOL_GPL(pci_power_names); -unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; +unsigned int pci_pm_d3_delay; + +static void pci_dev_d3_sleep(struct pci_dev *dev) +{ + unsigned int delay = dev->d3_delay; + + if (delay < pci_pm_d3_delay) + delay = pci_pm_d3_delay; + + msleep(delay); +} #ifdef CONFIG_PCI_DOMAINS int pci_domains_supported = 1; @@ -522,7 +532,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) /* Mandatory power management transition delays */ /* see PCI PM 1.1 5.6.1 table 18 */ if (state == PCI_D3hot || dev->current_state == PCI_D3hot) - msleep(pci_pm_d3_delay); + pci_dev_d3_sleep(dev); else if (state == PCI_D2 || dev->current_state == PCI_D2) udelay(PCI_PM_D2_DELAY); @@ -1409,6 +1419,7 @@ void pci_pm_init(struct pci_dev *dev) } dev->pm_cap = pm; + dev->d3_delay = PCI_PM_D3_WAIT; dev->d1_support = false; dev->d2_support = false; @@ -2247,12 +2258,12 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) csr &= ~PCI_PM_CTRL_STATE_MASK; csr |= PCI_D3hot; pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); - msleep(pci_pm_d3_delay); + pci_dev_d3_sleep(dev); csr &= ~PCI_PM_CTRL_STATE_MASK; csr |= PCI_D0; pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); - msleep(pci_pm_d3_delay); + pci_dev_d3_sleep(dev); return 0; } -- cgit v1.2.3 From b49bfd32901625e4adcfee011d2b32a43b4db67d Mon Sep 17 00:00:00 2001 From: "Youquan,Song" Date: Thu, 17 Dec 2009 08:22:48 -0500 Subject: PCIe AER: prevent AER injection if hardware masks error reporting The Correcteable/Uncorrectable Error Mask Registers are used by PCIe AER driver which will controls the reporting of individual errors to PCIe RC via PCIe error messages. If hardware masks special error reporting to RC, the aer_inject driver should not inject aer error. Acked-by: Andi Kleen Signed-off-by: Youquan, Song Acked-by: Ying, Huang Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aer/aer_inject.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index dd7155a037e..8c30a9544d6 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -321,7 +321,7 @@ static int aer_inject(struct aer_error_inj *einj) unsigned long flags; unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn); int pos_cap_err, rp_pos_cap_err; - u32 sever; + u32 sever, mask; int ret = 0; dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); @@ -374,6 +374,24 @@ static int aer_inject(struct aer_error_inj *einj) err->header_log2 = einj->header_log2; err->header_log3 = einj->header_log3; + pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &mask); + if (einj->cor_status && !(einj->cor_status & ~mask)) { + ret = -EINVAL; + printk(KERN_WARNING "The correctable error(s) is masked " + "by device\n"); + spin_unlock_irqrestore(&inject_lock, flags); + goto out_put; + } + + pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, &mask); + if (einj->uncor_status && !(einj->uncor_status & ~mask)) { + ret = -EINVAL; + printk(KERN_WARNING "The uncorrectable error(s) is masked " + "by device\n"); + spin_unlock_irqrestore(&inject_lock, flags); + goto out_put; + } + rperr = __find_aer_error_by_dev(rpdev); if (!rperr) { rperr = rperr_alloc; -- cgit v1.2.3 From dc2f9c5a13de4f9fd63f49f54add40b2924f66cd Mon Sep 17 00:00:00 2001 From: Li Jie Date: Thu, 31 Dec 2009 16:03:16 +0100 Subject: ARM: 5865/1: nuc900 ethernet driver needs mii nuc900 ethernet driver uses mii_xx_xx serials api, so mii module should be selected. Signed-off-by: lijie Acked-by: Wan ZongShun Signed-off-by: Russell King --- drivers/net/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig index c37ee9e6b67..39e1c0d3947 100644 --- a/drivers/net/arm/Kconfig +++ b/drivers/net/arm/Kconfig @@ -68,6 +68,7 @@ config W90P910_ETH tristate "Nuvoton w90p910 Ethernet support" depends on ARM && ARCH_W90X900 select PHYLIB + select MII help Say Y here if you want to use built-in Ethernet ports on w90p910 processor. -- cgit v1.2.3 From b9597a1c6fa6cbc938f14ab6a7fe09047b3a346b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 4 Jan 2010 19:12:02 -0500 Subject: drm/radeon/kms: fallback to default connector table if necessary for combios Some early combios radeon cards don't have a connector table or dac table in the bios, if they do not, fallback to the default tables. Should fix kernel bug 14963. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 91d72b70abc..1fb2f029d7e 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -329,8 +329,11 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) ret = radeon_get_atom_connector_info_from_object_table(dev); else ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); - } else + } else { ret = radeon_get_legacy_connector_info_from_bios(dev); + if (ret == false) + ret = radeon_get_legacy_connector_info_from_table(dev); + } } else { if (!ASIC_IS_AVIVO(rdev)) ret = radeon_get_legacy_connector_info_from_table(dev); -- cgit v1.2.3 From 246263ccc31e4ba2886cca17000bf09ea683eac5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 29 Dec 2009 12:09:17 -0500 Subject: drm/radeon/kms: add primary dac adj values table Look up primary dac adj values from the table if there is no bios or bios dac table to reference. The lookup table may need to be adjusted for certain families. Should fix kernel bug 14945. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 50 +++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index fd94dbca33a..58f342659cc 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -595,6 +595,34 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) return false; } +static const uint32_t default_primarydac_adj[CHIP_LAST] = { + 0x00000808, /* r100 */ + 0x00000808, /* rv100 */ + 0x00000808, /* rs100 */ + 0x00000808, /* rv200 */ + 0x00000808, /* rs200 */ + 0x00000808, /* r200 */ + 0x00000808, /* rv250 */ + 0x00000000, /* rs300 */ + 0x00000808, /* rv280 */ + 0x00000808, /* r300 */ + 0x00000808, /* r350 */ + 0x00000808, /* rv350 */ + 0x00000808, /* rv380 */ + 0x00000808, /* r420 */ + 0x00000808, /* r423 */ + 0x00000808, /* rv410 */ + 0x00000000, /* rs400 */ + 0x00000000, /* rs480 */ +}; + +static void radeon_legacy_get_primary_dac_info_from_table(struct radeon_device *rdev, + struct radeon_encoder_primary_dac *p_dac) +{ + p_dac->ps2_pdac_adj = default_primarydac_adj[rdev->family]; + return; +} + struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder) @@ -604,20 +632,20 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct uint16_t dac_info; uint8_t rev, bg, dac; struct radeon_encoder_primary_dac *p_dac = NULL; + int found = 0; - if (rdev->bios == NULL) + p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), + GFP_KERNEL); + + if (!p_dac) return NULL; + if (rdev->bios == NULL) + goto out; + /* check CRT table */ dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); if (dac_info) { - p_dac = - kzalloc(sizeof(struct radeon_encoder_primary_dac), - GFP_KERNEL); - - if (!p_dac) - return NULL; - rev = RBIOS8(dac_info) & 0x3; if (rev < 2) { bg = RBIOS8(dac_info + 0x2) & 0xf; @@ -628,9 +656,13 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct dac = RBIOS8(dac_info + 0x3) & 0xf; p_dac->ps2_pdac_adj = (bg << 8) | (dac); } - + found = 1; } +out: + if (!found) /* fallback to defaults */ + radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); + return p_dac; } -- cgit v1.2.3 From 1d3d51b6d2d6fb51c6c30a8c7ed0fd939f6100bf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 28 Dec 2009 13:45:23 -0500 Subject: drm/radeon/kms: add missing breaks in i2c and ss lookups Should fix fdo bug 25741 Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 321044bef71..41dd8ebff21 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -114,6 +114,7 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev i2c.i2c_id = gpio->sucI2cId.ucAccess; i2c.valid = true; + break; } } @@ -1026,6 +1027,7 @@ static struct radeon_atom_ss *radeon_atombios_get_ss_info(struct ss->delay = ss_info->asSS_Info[i].ucSS_Delay; ss->range = ss_info->asSS_Info[i].ucSS_Range; ss->refdiv = ss_info->asSS_Info[i].ucRecommendedRef_Div; + break; } } } -- cgit v1.2.3 From 59b015133cd0034f5904a76969d73476380aac46 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 5 Jan 2010 17:56:02 -0800 Subject: Input: serio - fix potential deadlock when unbinding drivers sysfs_remove_group() waits for sysfs attributes to be removed, therefore we do not need to worry about driver-specific attributes being accessed after driver has been detached from the device. In fact, attempts to take serio->drv_mutex in attribute methods may lead to the following deadlock: sysfs_read_file() fill_read_buffer() sysfs_get_active_two() psmouse_attr_show_helper() serio_pin_driver() serio_disconnect_driver() mutex_lock(&serio->drv_mutex); <--------> mutex_lock(&serio_drv_mutex); psmouse_disconnect() sysfs_remove_group(... psmouse_attr_group); .... sysfs_deactivate(); wait_for_completion(); Fix this by removing calls to serio_[un]pin_driver() and functions themselves and using driver-private mutexes to serialize access to attribute's set() methods that may change device state. Signed-off-by: Eric W. Biederman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 59 ++++++++++++++++---------------------- drivers/input/mouse/psmouse-base.c | 32 ++------------------- 2 files changed, 28 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 1f5e2ce327d..1cf32a7814d 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -225,8 +225,10 @@ struct atkbd { struct delayed_work event_work; unsigned long event_jiffies; - struct mutex event_mutex; unsigned long event_mask; + + /* Serializes reconnect(), attr->set() and event work */ + struct mutex mutex; }; /* @@ -577,7 +579,7 @@ static void atkbd_event_work(struct work_struct *work) { struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); - mutex_lock(&atkbd->event_mutex); + mutex_lock(&atkbd->mutex); if (!atkbd->enabled) { /* @@ -596,7 +598,7 @@ static void atkbd_event_work(struct work_struct *work) atkbd_set_repeat_rate(atkbd); } - mutex_unlock(&atkbd->event_mutex); + mutex_unlock(&atkbd->mutex); } /* @@ -612,7 +614,7 @@ static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit) atkbd->event_jiffies = jiffies; set_bit(event_bit, &atkbd->event_mask); - wmb(); + mb(); schedule_delayed_work(&atkbd->event_work, delay); } @@ -849,12 +851,13 @@ static void atkbd_disconnect(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); + sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); + atkbd_disable(atkbd); /* make sure we don't have a command in flight */ cancel_delayed_work_sync(&atkbd->event_work); - sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); input_unregister_device(atkbd->dev); serio_close(serio); serio_set_drvdata(serio, NULL); @@ -1087,7 +1090,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->dev = dev; ps2_init(&atkbd->ps2dev, serio); INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); - mutex_init(&atkbd->event_mutex); + mutex_init(&atkbd->mutex); switch (serio->id.type) { @@ -1160,19 +1163,23 @@ static int atkbd_reconnect(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); struct serio_driver *drv = serio->drv; + int retval = -1; if (!atkbd || !drv) { printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); return -1; } + mutex_lock(&atkbd->mutex); + atkbd_disable(atkbd); if (atkbd->write) { if (atkbd_probe(atkbd)) - return -1; + goto out; + if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) - return -1; + goto out; atkbd_activate(atkbd); @@ -1190,8 +1197,11 @@ static int atkbd_reconnect(struct serio *serio) } atkbd_enable(atkbd); + retval = 0; - return 0; + out: + mutex_unlock(&atkbd->mutex); + return retval; } static struct serio_device_id atkbd_serio_ids[] = { @@ -1235,47 +1245,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)) { struct serio *serio = to_serio_port(dev); - int retval; - - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &atkbd_drv) { - retval = -ENODEV; - goto out; - } - - retval = handler((struct atkbd *)serio_get_drvdata(serio), buf); + struct atkbd *atkbd = serio_get_drvdata(serio); -out: - serio_unpin_driver(serio); - return retval; + return handler(atkbd, buf); } static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, ssize_t (*handler)(struct atkbd *, const char *, size_t)) { struct serio *serio = to_serio_port(dev); - struct atkbd *atkbd; + struct atkbd *atkbd = serio_get_drvdata(serio); int retval; - retval = serio_pin_driver(serio); + retval = mutex_lock_interruptible(&atkbd->mutex); if (retval) return retval; - if (serio->drv != &atkbd_drv) { - retval = -ENODEV; - goto out; - } - - atkbd = serio_get_drvdata(serio); atkbd_disable(atkbd); retval = handler(atkbd, buf, count); atkbd_enable(atkbd); -out: - serio_unpin_driver(serio); + mutex_unlock(&atkbd->mutex); + return retval; } diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 401ac6b6edd..d59e18b24ed 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1450,24 +1450,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de struct serio *serio = to_serio_port(dev); struct psmouse_attribute *attr = to_psmouse_attr(devattr); struct psmouse *psmouse; - int retval; - - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out; - } psmouse = serio_get_drvdata(serio); - retval = attr->show(psmouse, attr->data, buf); - -out: - serio_unpin_driver(serio); - return retval; + return attr->show(psmouse, attr->data, buf); } ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, @@ -1478,18 +1464,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev struct psmouse *psmouse, *parent = NULL; int retval; - retval = serio_pin_driver(serio); - if (retval) - return retval; - - if (serio->drv != &psmouse_drv) { - retval = -ENODEV; - goto out_unpin; - } - retval = mutex_lock_interruptible(&psmouse_mutex); if (retval) - goto out_unpin; + goto out; psmouse = serio_get_drvdata(serio); @@ -1519,8 +1496,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev out_unlock: mutex_unlock(&psmouse_mutex); - out_unpin: - serio_unpin_driver(serio); + out: return retval; } @@ -1582,9 +1558,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co } mutex_unlock(&psmouse_mutex); - serio_unpin_driver(serio); serio_unregister_child_port(serio); - serio_pin_driver_uninterruptible(serio); mutex_lock(&psmouse_mutex); if (serio->drv != &psmouse_drv) { -- cgit v1.2.3 From 0ef7a26af1278f7ec0b718148e88f01ba1953835 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 Jan 2010 17:56:02 -0800 Subject: Input: atkbd - fix canceling event_work in disconnect We need to first unregister input device and only then cancel event work since events can arrive (and cause event work to get scheduled again) until input_unregister_device() returns. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 1cf32a7814d..7b4056292ea 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -855,10 +855,16 @@ static void atkbd_disconnect(struct serio *serio) atkbd_disable(atkbd); - /* make sure we don't have a command in flight */ + input_unregister_device(atkbd->dev); + + /* + * Make sure we don't have a command in flight. + * Note that since atkbd->enabled is false event work will keep + * rescheduling itself until it gets canceled and will not try + * accessing freed input device or serio port. + */ cancel_delayed_work_sync(&atkbd->event_work); - input_unregister_device(atkbd->dev); serio_close(serio); serio_set_drvdata(serio, NULL); kfree(atkbd); -- cgit v1.2.3 From 30a589fde0162aa4dac7c69803aeee8fbe8d1b82 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 5 Jan 2010 17:56:04 -0800 Subject: Input: evdev - be less aggressive about sending SIGIO notifies When using realtime signals, we'll enqueue one signal for every event. This is unfortunate, because (for example) keyboard presses are three events: key, msc scancode, and syn. They'll be enqueued fast enough in kernel space that all three events will be ready to read by the time userspace runs, so the first invocation of the signal handler will read all three events, but then the second two invocations still have to run to do no work. Instead, only send the SIGIO notification on syn events. This is a slight abuse of SIGIO semantics, in principle it ought to fire as soon as any events are readable. But it matches evdev semantics, which is more important since SIGIO is rather vaguely defined to begin with. Signed-off-by: Adam Jackson Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index dee6706038a..258c639571b 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client, client->head &= EVDEV_BUFFER_SIZE - 1; spin_unlock(&client->buffer_lock); - kill_fasync(&client->fasync, SIGIO, POLL_IN); + if (event->type == EV_SYN) + kill_fasync(&client->fasync, SIGIO, POLL_IN); } /* -- cgit v1.2.3 From 861a64428c0786a5cfa2ffb36b2f8058dea5dda0 Mon Sep 17 00:00:00 2001 From: Miguel Aguilar Date: Wed, 6 Jan 2010 00:06:50 -0800 Subject: Input: davinci_keyscan - add device_enable method to platform data Add a function pointer in the platform data of the DaVinci Keyscan driver called device_enable, in order to perform board specific actions when the device is initialized, like setup the PINMUX configuration. Signed-off-by: Miguel Aguilar Signed-off-by: Kevin Hilman Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/davinci_keyscan.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 6e52d855f63..d410d7a52f1 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -174,6 +174,14 @@ static int __init davinci_ks_probe(struct platform_device *pdev) struct davinci_ks_platform_data *pdata = pdev->dev.platform_data; int error, i; + if (pdata->device_enable) { + error = pdata->device_enable(dev); + if (error < 0) { + dev_dbg(dev, "device enable function failed\n"); + return error; + } + } + if (!pdata->keymap) { dev_dbg(dev, "no keymap from pdata\n"); return -EINVAL; -- cgit v1.2.3 From 6f2701b79f2ee0c5eb946e8a87993acbe8041da3 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 6 Jan 2010 00:32:48 -0800 Subject: Input: bcm5974 - report ABS_MT events Make bcm5974 report raw multi-touch (MT) data in the form of ABS_MT events. [dtor@mail.ru: get rid of module option, always report all events] Signed-off-by: Henrik Rydberg Signed-off-by: Andrew Morton Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/bcm5974.c | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 0d1d33468b4..4f8fe0886b2 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -139,6 +139,7 @@ struct tp_finger { /* trackpad finger data size, empirically at least ten fingers */ #define SIZEOF_FINGER sizeof(struct tp_finger) #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) +#define MAX_FINGER_ORIENTATION 16384 /* device-specific parameters */ struct bcm5974_param { @@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_Y, 0, cfg->y.dim, cfg->y.fuzz, 0); + /* finger touch area */ + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + /* finger approach area */ + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, + cfg->w.devmin, cfg->w.devmax, 0, 0); + /* finger orientation */ + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, + -MAX_FINGER_ORIENTATION, + MAX_FINGER_ORIENTATION, 0, 0); + /* finger position */ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + cfg->x.devmin, cfg->x.devmax, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + cfg->y.devmin, cfg->y.devmax, 0, 0); + __set_bit(EV_KEY, input_dev->evbit); __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOOL_FINGER, input_dev->keybit); @@ -310,13 +331,29 @@ static int report_bt_state(struct bcm5974 *dev, int size) return 0; } +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_ORIENTATION, + MAX_FINGER_ORIENTATION - raw2int(f->orientation)); + input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); + input_report_abs(input, ABS_MT_POSITION_Y, + cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y)); + input_mt_sync(input); +} + /* report trackpad data as logical trackpad state */ static int report_tp_state(struct bcm5974 *dev, int size) { const struct bcm5974_config *c = &dev->cfg; const struct tp_finger *f; struct input_dev *input = dev->input; - int raw_p, raw_w, raw_x, raw_y, raw_n; + int raw_p, raw_w, raw_x, raw_y, raw_n, i; int ptest, origin, ibt = 0, nmin = 0, nmax = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; @@ -329,6 +366,11 @@ static int report_tp_state(struct bcm5974 *dev, int size) /* always track the first finger; when detached, start over */ if (raw_n) { + + /* report raw trackpad data */ + for (i = 0; i < raw_n; i++) + report_finger_data(input, c, &f[i]); + raw_p = raw2int(f->force_major); raw_w = raw2int(f->size_major); raw_x = raw2int(f->abs_x); -- cgit v1.2.3 From 76446cac68568fc7f5168a27deaf803ed22a4360 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Dec 2009 22:05:42 -0500 Subject: drm/i915: execbuf2 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new execbuf ioctl, execbuf2, for use by clients that want to control fence register allocation more finely. The buffer passed in to the new ioctl includes a new relocation type to indicate whether a given object needs a fence register assigned for the command buffer in question. Compatibility with the existing execbuf ioctl is implemented in terms of the new code, preserving the assumption that fence registers are required for pre-965 rendering commands. Signed-off-by: Jesse Barnes [ickle: Remove pre-emptive clear_fence_reg()] Signed-off-by: Chris Wilson Signed-off-by: Kristian Høgsberg [anholt: Removed dmesg spam] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 7 +- drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 239 +++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_tiling.c | 46 +++---- 4 files changed, 219 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index e3e5d509423..d67be655c53 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -813,9 +813,13 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_PAGEFLIPPING: value = 1; break; + case I915_PARAM_HAS_EXECBUF2: + /* depends on GEM */ + value = dev_priv->has_gem; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", - param->param); + param->param); return -EINVAL; } @@ -1646,6 +1650,7 @@ struct drm_ioctl_desc i915_ioctls[] = { 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_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH), DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9a05f1a0102..7eb4ad51034 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -815,6 +815,8 @@ int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_execbuffer2(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_pin_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, @@ -881,6 +883,9 @@ void i915_gem_shrinker_exit(void); void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj); void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj); +bool i915_tiling_ok(struct drm_device *dev, int stride, int size, + int tiling_mode); +bool i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj); /* i915_gem_debug.c */ void i915_gem_dump_object(struct drm_gem_object *obj, int len, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9e81a0ddafa..0330c3aa803 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3199,7 +3199,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, static int i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, struct drm_file *file_priv, - struct drm_i915_gem_exec_object *entry, + struct drm_i915_gem_exec_object2 *entry, struct drm_i915_gem_relocation_entry *relocs) { struct drm_device *dev = obj->dev; @@ -3207,12 +3207,35 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, struct drm_i915_gem_object *obj_priv = obj->driver_private; int i, ret; void __iomem *reloc_page; + bool need_fence; + + need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE && + obj_priv->tiling_mode != I915_TILING_NONE; + + /* Check fence reg constraints and rebind if necessary */ + if (need_fence && !i915_obj_fenceable(dev, obj)) + i915_gem_object_unbind(obj); /* Choose the GTT offset for our buffer and put it there. */ ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); if (ret) return ret; + /* + * Pre-965 chips need a fence register set up in order to + * properly handle blits to/from tiled surfaces. + */ + if (need_fence) { + ret = i915_gem_object_get_fence_reg(obj); + if (ret != 0) { + if (ret != -EBUSY && ret != -ERESTARTSYS) + DRM_ERROR("Failure to install fence: %d\n", + ret); + i915_gem_object_unpin(obj); + return ret; + } + } + entry->offset = obj_priv->gtt_offset; /* Apply the relocations, using the GTT aperture to avoid cache @@ -3374,7 +3397,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, */ static int i915_dispatch_gem_execbuffer(struct drm_device *dev, - struct drm_i915_gem_execbuffer *exec, + struct drm_i915_gem_execbuffer2 *exec, struct drm_clip_rect *cliprects, uint64_t exec_offset) { @@ -3464,7 +3487,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) } static int -i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, +i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list, uint32_t buffer_count, struct drm_i915_gem_relocation_entry **relocs) { @@ -3479,8 +3502,10 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, } *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); - if (*relocs == NULL) + if (*relocs == NULL) { + DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count); return -ENOMEM; + } for (i = 0; i < buffer_count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; @@ -3504,7 +3529,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, } static int -i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list, +i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list, uint32_t buffer_count, struct drm_i915_gem_relocation_entry *relocs) { @@ -3537,7 +3562,7 @@ err: } static int -i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec, +i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, uint64_t exec_offset) { uint32_t exec_start, exec_len; @@ -3590,18 +3615,18 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev, } int -i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) +i915_gem_do_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv, + struct drm_i915_gem_execbuffer2 *args, + struct drm_i915_gem_exec_object2 *exec_list) { drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_execbuffer *args = data; - struct drm_i915_gem_exec_object *exec_list = NULL; struct drm_gem_object **object_list = NULL; struct drm_gem_object *batch_obj; struct drm_i915_gem_object *obj_priv; struct drm_clip_rect *cliprects = NULL; struct drm_i915_gem_relocation_entry *relocs; - int ret, ret2, i, pinned = 0; + int ret = 0, ret2, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains, reloc_index; int pin_tries, flips; @@ -3615,25 +3640,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); return -EINVAL; } - /* Copy in the exec list from userland */ - exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); - if (exec_list == NULL || object_list == NULL) { - DRM_ERROR("Failed to allocate exec or object list " - "for %d buffers\n", + if (object_list == NULL) { + DRM_ERROR("Failed to allocate object list for %d buffers\n", args->buffer_count); ret = -ENOMEM; goto pre_mutex_err; } - ret = copy_from_user(exec_list, - (struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - sizeof(*exec_list) * args->buffer_count); - if (ret != 0) { - DRM_ERROR("copy %d exec entries failed %d\n", - args->buffer_count, ret); - goto pre_mutex_err; - } if (args->num_cliprects != 0) { cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects), @@ -3885,20 +3898,6 @@ err: mutex_unlock(&dev->struct_mutex); - if (!ret) { - /* Copy the new buffer offsets back to the user's exec list. */ - ret = copy_to_user((struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - exec_list, - sizeof(*exec_list) * args->buffer_count); - if (ret) { - ret = -EFAULT; - DRM_ERROR("failed to copy %d exec entries " - "back to user (%d)\n", - args->buffer_count, ret); - } - } - /* Copy the updated relocations out regardless of current error * state. Failure to update the relocs would mean that the next * time userland calls execbuf, it would do so with presumed offset @@ -3915,12 +3914,158 @@ err: pre_mutex_err: drm_free_large(object_list); - drm_free_large(exec_list); kfree(cliprects); return ret; } +/* + * Legacy execbuffer just creates an exec2 list from the original exec object + * list array and passes it to the real function. + */ +int +i915_gem_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_execbuffer *args = data; + struct drm_i915_gem_execbuffer2 exec2; + struct drm_i915_gem_exec_object *exec_list = NULL; + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret, i; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + /* Copy in the exec list from userland */ + exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); + exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + if (exec_list == NULL || exec2_list == NULL) { + DRM_ERROR("Failed to allocate exec list for %d buffers\n", + args->buffer_count); + drm_free_large(exec_list); + drm_free_large(exec2_list); + return -ENOMEM; + } + ret = copy_from_user(exec_list, + (struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + sizeof(*exec_list) * args->buffer_count); + if (ret != 0) { + DRM_ERROR("copy %d exec entries failed %d\n", + args->buffer_count, ret); + drm_free_large(exec_list); + drm_free_large(exec2_list); + return -EFAULT; + } + + for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].handle = exec_list[i].handle; + exec2_list[i].relocation_count = exec_list[i].relocation_count; + exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; + exec2_list[i].alignment = exec_list[i].alignment; + exec2_list[i].offset = exec_list[i].offset; + if (!IS_I965G(dev)) + exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; + else + exec2_list[i].flags = 0; + } + + exec2.buffers_ptr = args->buffers_ptr; + exec2.buffer_count = args->buffer_count; + exec2.batch_start_offset = args->batch_start_offset; + exec2.batch_len = args->batch_len; + exec2.DR1 = args->DR1; + exec2.DR4 = args->DR4; + exec2.num_cliprects = args->num_cliprects; + exec2.cliprects_ptr = args->cliprects_ptr; + exec2.flags = 0; + + ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ + for (i = 0; i < args->buffer_count; i++) + exec_list[i].offset = exec2_list[i].offset; + /* ... and back out to userspace */ + ret = copy_to_user((struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + exec_list, + sizeof(*exec_list) * args->buffer_count); + if (ret) { + ret = -EFAULT; + DRM_ERROR("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + } + } else { + DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); + } + + drm_free_large(exec_list); + drm_free_large(exec2_list); + return ret; +} + +int +i915_gem_execbuffer2(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_execbuffer2 *args = data; + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + if (exec2_list == NULL) { + DRM_ERROR("Failed to allocate exec list for %d buffers\n", + args->buffer_count); + return -ENOMEM; + } + ret = copy_from_user(exec2_list, + (struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + sizeof(*exec2_list) * args->buffer_count); + if (ret != 0) { + DRM_ERROR("copy %d exec entries failed %d\n", + args->buffer_count, ret); + drm_free_large(exec2_list); + return -EFAULT; + } + + ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ + ret = copy_to_user((struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + exec2_list, + sizeof(*exec2_list) * args->buffer_count); + if (ret) { + ret = -EFAULT; + DRM_ERROR("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + } + } + + drm_free_large(exec2_list); + return ret; +} + int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) { @@ -3934,19 +4079,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) if (ret) return ret; } - /* - * Pre-965 chips need a fence register set up in order to - * properly handle tiled surfaces. - */ - if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) { - ret = i915_gem_object_get_fence_reg(obj); - if (ret != 0) { - if (ret != -EBUSY && ret != -ERESTARTSYS) - DRM_ERROR("Failure to install fence: %d\n", - ret); - return ret; - } - } + obj_priv->pin_count++; /* If the object is not active and not pending a flush, diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 30d6af6c09b..df278b2685b 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -304,35 +304,39 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) /** - * Returns the size of the fence for a tiled object of the given size. + * Returns whether an object is currently fenceable. If not, it may need + * to be unbound and have its pitch adjusted. */ -static int -i915_get_fence_size(struct drm_device *dev, int size) +bool +i915_obj_fenceable(struct drm_device *dev, struct drm_gem_object *obj) { - int i; - int start; + struct drm_i915_gem_object *obj_priv = obj->driver_private; if (IS_I965G(dev)) { /* The 965 can have fences at any page boundary. */ - return ALIGN(size, 4096); + if (obj->size & 4095) + return false; + return true; + } else if (IS_I9XX(dev)) { + if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) + return false; } else { - /* Align the size to a power of two greater than the smallest - * fence size. - */ - if (IS_I9XX(dev)) - start = 1024 * 1024; - else - start = 512 * 1024; + if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) + return false; + } - for (i = start; i < size; i <<= 1) - ; + /* Power of two sized... */ + if (obj->size & (obj->size - 1)) + return false; - return i; - } + /* Objects must be size aligned as well */ + if (obj_priv->gtt_offset & (obj->size - 1)) + return false; + return true; } /* Check pitch constriants for all chips & tiling formats */ -static bool +bool i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) { int tile_width; @@ -384,12 +388,6 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) if (stride & (stride - 1)) return false; - /* We don't 0handle the aperture area covered by the fence being bigger - * than the object size. - */ - if (i915_get_fence_size(dev, size) != size) - return false; - return true; } -- cgit v1.2.3 From 1d3c36ad4122651018599d4e3c9be0cccfbfb939 Mon Sep 17 00:00:00 2001 From: Andrew Lutomirski Date: Mon, 21 Dec 2009 10:10:22 -0500 Subject: drm/i915: Fix RC6 suspend/resume We restored RC6 twice on resume, even with modesetting off. Instead, only restore it once and skip RC6 initialization entirely in non-KMS mode. Signed-off-by: Andy Lutomirski Tested-by: Jeff Chua Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_suspend.c | 12 ------------ drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 1 insertion(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7eb4ad51034..29dd6762696 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -307,8 +307,6 @@ typedef struct drm_i915_private { u32 saveDSPACNTR; u32 saveDSPBCNTR; u32 saveDSPARB; - u32 saveRENDERSTANDBY; - u32 savePWRCTXA; u32 saveHWS; u32 savePIPEACONF; u32 savePIPEBCONF; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index d5ebb00a9d4..a3b90c9561d 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -732,12 +732,6 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); - /* Render Standby */ - if (I915_HAS_RC6(dev)) { - dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); - dev_priv->savePWRCTXA = I915_READ(PWRCTXA); - } - /* Hardware status page */ dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -793,12 +787,6 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); - /* Render Standby */ - if (I915_HAS_RC6(dev)) { - I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); - I915_WRITE(PWRCTXA, dev_priv->savePWRCTXA); - } - /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c21dede6461..089b1df5448 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4593,7 +4593,7 @@ void intel_init_clock_gating(struct drm_device *dev) * GPU can automatically power down the render unit if given a page * to save state. */ - if (I915_HAS_RC6(dev)) { + if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { struct drm_gem_object *pwrctx; struct drm_i915_gem_object *obj_priv; int ret; -- cgit v1.2.3 From cda9d05c499093c67b4a376a15009923acc2127a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 Dec 2009 11:11:13 -0800 Subject: drm/i915: remove render reclock support This code generally fails to adjust the render clock, and when it does, it conflicts with some other register settings and can cause problems. So remove this code altogether. I'm reworking it now to do the right thing, but the only bit it will share is the VBT check for whether reclocking is supported, so I'm leaving that bit. Reverts most of 652c393a3368af84359da37c45afc35a91144960 ("add dynamic clock frequency control"), though for many the regressions showed up in the later 181a5336d6cc836f05507410d66988c483ad0154 ("Fix render reclock availability detection"). Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 132 +---------------------------------- 1 file changed, 2 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 089b1df5448..9187a1736b0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3779,125 +3779,6 @@ static void intel_gpu_idle_timer(unsigned long arg) queue_work(dev_priv->wq, &dev_priv->idle_work); } -void intel_increase_renderclock(struct drm_device *dev, bool schedule) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (IS_IRONLAKE(dev)) - return; - - if (!dev_priv->render_reclock_avail) { - DRM_DEBUG_DRIVER("not reclocking render clock\n"); - return; - } - - /* Restore render clock frequency to original value */ - if (IS_G4X(dev) || IS_I9XX(dev)) - pci_write_config_word(dev->pdev, GCFGC, dev_priv->orig_clock); - else if (IS_I85X(dev)) - pci_write_config_word(dev->pdev, HPLLCC, dev_priv->orig_clock); - DRM_DEBUG_DRIVER("increasing render clock frequency\n"); - - /* Schedule downclock */ - if (schedule) - mod_timer(&dev_priv->idle_timer, jiffies + - msecs_to_jiffies(GPU_IDLE_TIMEOUT)); -} - -void intel_decrease_renderclock(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (IS_IRONLAKE(dev)) - return; - - if (!dev_priv->render_reclock_avail) { - DRM_DEBUG_DRIVER("not reclocking render clock\n"); - return; - } - - if (IS_G4X(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~GM45_GC_RENDER_CLOCK_MASK; - gcfgc |= GM45_GC_RENDER_CLOCK_266_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I965G(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I965_GC_RENDER_CLOCK_MASK; - gcfgc |= I965_GC_RENDER_CLOCK_267_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I945G(dev) || IS_I945GM(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I945_GC_RENDER_CLOCK_MASK; - gcfgc |= I945_GC_RENDER_CLOCK_166_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I915G(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~I915_GC_RENDER_CLOCK_MASK; - gcfgc |= I915_GC_RENDER_CLOCK_166_MHZ; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } else if (IS_I85X(dev)) { - u16 hpllcc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, HPLLCC, &hpllcc); - - /* Up to maximum... */ - hpllcc &= ~GC_CLOCK_CONTROL_MASK; - hpllcc |= GC_CLOCK_133_200; - - pci_write_config_word(dev->pdev, HPLLCC, hpllcc); - } - DRM_DEBUG_DRIVER("decreasing render clock frequency\n"); -} - -/* Note that no increase function is needed for this - increase_renderclock() - * will also rewrite these bits - */ -void intel_decrease_displayclock(struct drm_device *dev) -{ - if (IS_IRONLAKE(dev)) - return; - - if (IS_I945G(dev) || IS_I945GM(dev) || IS_I915G(dev) || - IS_I915GM(dev)) { - u16 gcfgc; - - /* Adjust render clock... */ - pci_read_config_word(dev->pdev, GCFGC, &gcfgc); - - /* Down to minimum... */ - gcfgc &= ~0xf0; - gcfgc |= 0x80; - - pci_write_config_word(dev->pdev, GCFGC, gcfgc); - } -} - #define CRTC_IDLE_TIMEOUT 1000 /* ms */ static void intel_crtc_idle_timer(unsigned long arg) @@ -4011,12 +3892,6 @@ static void intel_idle_update(struct work_struct *work) mutex_lock(&dev->struct_mutex); - /* GPU isn't processing, downclock it. */ - if (!dev_priv->busy) { - intel_decrease_renderclock(dev); - intel_decrease_displayclock(dev); - } - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { /* Skip inactive CRTCs */ if (!crtc->fb) @@ -4050,13 +3925,11 @@ void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; - if (!dev_priv->busy) { + if (!dev_priv->busy) dev_priv->busy = true; - intel_increase_renderclock(dev, true); - } else { + else mod_timer(&dev_priv->idle_timer, jiffies + msecs_to_jiffies(GPU_IDLE_TIMEOUT)); - } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { if (!crtc->fb) @@ -4784,7 +4657,6 @@ void intel_modeset_cleanup(struct drm_device *dev) del_timer_sync(&intel_crtc->idle_timer); } - intel_increase_renderclock(dev, false); del_timer_sync(&dev_priv->idle_timer); if (dev_priv->display.disable_fbc) -- cgit v1.2.3 From 69e302a998ddfc3bd99033052f6d6152a46e7d6e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 23 Dec 2009 14:14:34 +0100 Subject: drm/i915: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9187a1736b0..af61dd915f2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2448,7 +2448,7 @@ static void pineview_enable_cxsr(struct drm_device *dev, unsigned long clock, * A value of 5us seems to be a good balance; safe for very low end * platforms but not overly aggressive on lower latency configs. */ -const static int latency_ns = 5000; +static const int latency_ns = 5000; static int i9xx_get_fifo_size(struct drm_device *dev, int plane) { @@ -2559,7 +2559,7 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock, /* Calc sr entries for one plane configs */ if (sr_hdisplay && (!planea_clock || !planeb_clock)) { /* self-refresh has much higher latency */ - const static int sr_latency_ns = 12000; + static const int sr_latency_ns = 12000; sr_clock = planea_clock ? planea_clock : planeb_clock; line_time_us = ((sr_hdisplay * 1000) / sr_clock); @@ -2598,7 +2598,7 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock, /* Calc sr entries for one plane configs */ if (sr_hdisplay && (!planea_clock || !planeb_clock)) { /* self-refresh has much higher latency */ - const static int sr_latency_ns = 12000; + static const int sr_latency_ns = 12000; sr_clock = planea_clock ? planea_clock : planeb_clock; line_time_us = ((sr_hdisplay * 1000) / sr_clock); @@ -2667,7 +2667,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock, if (HAS_FW_BLC(dev) && sr_hdisplay && (!planea_clock || !planeb_clock)) { /* self-refresh has much higher latency */ - const static int sr_latency_ns = 6000; + static const int sr_latency_ns = 6000; sr_clock = planea_clock ? planea_clock : planeb_clock; line_time_us = ((sr_hdisplay * 1000) / sr_clock); -- cgit v1.2.3 From 29bd0ae25f8cb96b63560c2cbccec77b425e1603 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Nov 2009 14:08:52 -0800 Subject: drm/i915: fix unused var drivers/gpu/drm/i915/i915_dma.c: In function 'i915_driver_load': drivers/gpu/drm/i915/i915_dma.c:1114: warning: 'll_base' may be used uninitialized in this function Partly this is because gcc isn't smart enough. But `ll_base' does get used uninitialised in the DRM_DEBUG() call. Cc: Jesse Barnes Cc: Eric Anholt Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index d67be655c53..c2b11088a6e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1121,7 +1121,8 @@ static void i915_setup_compression(struct drm_device *dev, int size) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_mm_node *compressed_fb, *compressed_llb; - unsigned long cfb_base, ll_base; + unsigned long cfb_base; + unsigned long ll_base = 0; /* Leave 1M for line length buffer & misc. */ compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0); -- cgit v1.2.3 From 9ea8d05932c082a7ccbd9dc2e10687c88a70bd13 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Jan 2010 18:57:56 +0000 Subject: drm/i915: Hold struct mutex whilst pinning power context bo. Hugh found an error path where we were attempting to unref a bo without holding the struct mutex: [drm:intel_init_clock_gating] *ERROR* failed to pin power context: -16 ------------[ cut here ]------------ WARNING: at drivers/gpu/drm/drm_gem.c:438 drm_gem_object_free+0x20/0x5e() Hardware name: ESPRIMO Mobile V5505 Modules linked in: snd_pcm_oss snd_mixer_oss snd_seq snd_seq_device Pid: 3793, comm: s2ram Not tainted 2.6.33-rc2 #4 Call Trace: [<7815298e>] warn_slowpath_common+0x59/0x6b [<781529b3>] warn_slowpath_null+0x13/0x18 [<78317c1a>] ? drm_gem_object_free+0x20/0x5e [<78317c1a>] drm_gem_object_free+0x20/0x5e [<78317bfa>] ? drm_gem_object_free+0x0/0x5e [<7829df11>] kref_put+0x38/0x45 [<7833a5f0>] intel_init_clock_gating+0x232/0x271 [<78317bfa>] ? drm_gem_object_free+0x0/0x5e [<7832c307>] i915_restore_state+0x21a/0x2b3 [<7832379d>] i915_resume+0x3c/0xbb [<78174fe5>] ? trace_hardirqs_on_caller+0xfc/0x123 [<7831c756>] ? drm_class_resume+0x0/0x3e [<7831c78d>] drm_class_resume+0x37/0x3e [<78351e0a>] legacy_resume+0x1e/0x51 [<78351ece>] device_resume+0x91/0xab [<7831c756>] ? drm_class_resume+0x0/0x3e [<78352226>] dpm_resume+0x58/0x10f [<783522fb>] dpm_resume_end+0x1e/0x2c [<78180f80>] suspend_devices_and_enter+0x61/0x84 [<78180ff8>] enter_state+0x55/0x83 [<7818091c>] state_store+0x94/0xaa [<7829d09e>] kobj_attr_store+0x1e/0x23 [<782098e0>] sysfs_write_file+0x66/0x99 [<781cd2f0>] vfs_write+0x8a/0x108 [<781cd408>] sys_write+0x3c/0x63 [<78125c10>] sysenter_do_call+0x12/0x36 ---[ end trace a343537f29950fda ]--- It is in fact slightly more insiduous that first appears since we are attempting to not just free the object without the lock, but are trying to do the whole bo manipulation without holding the lock. Reported-by: Hugh Dickins Signed-off-by: Chris Wilson Cc: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 73 +++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index af61dd915f2..84705b7e01e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4414,6 +4414,42 @@ static const struct drm_mode_config_funcs intel_mode_funcs = { .fb_changed = intelfb_probe, }; +static struct drm_gem_object * +intel_alloc_power_context(struct drm_device *dev) +{ + struct drm_gem_object *pwrctx; + int ret; + + pwrctx = drm_gem_object_alloc(dev, 4096); + if (!pwrctx) { + DRM_DEBUG("failed to alloc power context, RC6 disabled\n"); + return NULL; + } + + mutex_lock(&dev->struct_mutex); + ret = i915_gem_object_pin(pwrctx, 4096); + if (ret) { + DRM_ERROR("failed to pin power context: %d\n", ret); + goto err_unref; + } + + ret = i915_gem_object_set_to_gtt_domain(pwrctx, 1); + if (ret) { + DRM_ERROR("failed to set-domain on power context: %d\n", ret); + goto err_unpin; + } + mutex_unlock(&dev->struct_mutex); + + return pwrctx; + +err_unpin: + i915_gem_object_unpin(pwrctx); +err_unref: + drm_gem_object_unreference(pwrctx); + mutex_unlock(&dev->struct_mutex); + return NULL; +} + void intel_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -4467,41 +4503,26 @@ void intel_init_clock_gating(struct drm_device *dev) * to save state. */ if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { - struct drm_gem_object *pwrctx; - struct drm_i915_gem_object *obj_priv; - int ret; + struct drm_i915_gem_object *obj_priv = NULL; if (dev_priv->pwrctx) { obj_priv = dev_priv->pwrctx->driver_private; } else { - pwrctx = drm_gem_object_alloc(dev, 4096); - if (!pwrctx) { - DRM_DEBUG("failed to alloc power context, " - "RC6 disabled\n"); - goto out; - } + struct drm_gem_object *pwrctx; - ret = i915_gem_object_pin(pwrctx, 4096); - if (ret) { - DRM_ERROR("failed to pin power context: %d\n", - ret); - drm_gem_object_unreference(pwrctx); - goto out; + pwrctx = intel_alloc_power_context(dev); + if (pwrctx) { + dev_priv->pwrctx = pwrctx; + obj_priv = pwrctx->driver_private; } - - i915_gem_object_set_to_gtt_domain(pwrctx, 1); - - dev_priv->pwrctx = pwrctx; - obj_priv = pwrctx->driver_private; } - I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); - I915_WRITE(MCHBAR_RENDER_STANDBY, - I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); + if (obj_priv) { + I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); + I915_WRITE(MCHBAR_RENDER_STANDBY, + I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); + } } - -out: - return; } /* Set up chip specific display functions */ -- cgit v1.2.3 From e3d8affb0d2d95f2da61e30ce86b33177feb91e8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 4 Jan 2010 18:57:57 +0000 Subject: drm/i915: Permit pinning whilst the device is 'suspended' As pinning (allocating and binding GTT memory) does not actually invoke GPU commands, it is safe, and indeed is attempted, during resumption from suspension: [drm:intel_init_clock_gating] *ERROR* failed to pin power context: -16 Signed-off-by: Chris Wilson Reported-by: Hugh Dickins Cc: stable@kernel.org Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0330c3aa803..21950ef987c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2582,9 +2582,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) bool retry_alloc = false; int ret; - if (dev_priv->mm.suspended) - return -EBUSY; - if (obj_priv->madv != I915_MADV_WILLNEED) { DRM_ERROR("Attempting to bind a purgeable object\n"); return -EINVAL; -- cgit v1.2.3 From 898822ce9561ab9b58a7eb60580a162a83dadecd Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:30 +0800 Subject: drm/i915: Enable/disable the dithering for LVDS based on VBT setting Enable/disable the dithering for LVDS based on VBT setting. On the 965/g4x platform the dithering flag is defined in LVDS register. And on the ironlake the dithering flag is defined in pipeconf register. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f79b13324fa..149d360d64a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -975,6 +975,8 @@ #define LVDS_PORT_EN (1 << 31) /* Selects pipe B for LVDS data. Must be set on pre-965. */ #define LVDS_PIPEB_SELECT (1 << 30) +/* LVDS dithering flag on 965/g4x platform */ +#define LVDS_ENABLE_DITHER (1 << 25) /* Enable border for unscaled (or aspect-scaled) display */ #define LVDS_BORDER_ENABLE (1 << 15) /* @@ -1744,6 +1746,8 @@ /* Display & cursor control */ +/* dithering flag on Ironlake */ +#define PIPE_ENABLE_DITHER (1 << 4) /* Pipe A */ #define PIPEADSL 0x70000 #define PIPEACONF 0x70008 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 84705b7e01e..0c9b79f2ab3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3195,7 +3195,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, * appropriately here, but we need to look more thoroughly into how * panels behave in the two modes. */ - + /* set the dithering flag */ + if (IS_I965G(dev)) { + if (dev_priv->lvds_dither) { + if (IS_IRONLAKE(dev)) + pipeconf |= PIPE_ENABLE_DITHER; + else + lvds |= LVDS_ENABLE_DITHER; + } else { + if (IS_IRONLAKE(dev)) + pipeconf &= ~PIPE_ENABLE_DITHER; + else + lvds &= ~LVDS_ENABLE_DITHER; + } + } I915_WRITE(lvds_reg, lvds); I915_READ(lvds_reg); } -- cgit v1.2.3 From 8faf3b317471179c02db339aa80955a2e88c036d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:31 +0800 Subject: drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake Make the BPC in FDI rx/transcoder be consistent with that in pipeconf on Ironlake. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c9b79f2ab3..63e8e9fd679 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1493,6 +1493,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B; u32 temp; int tries = 5, j, n; + u32 pipe_bpc; + + temp = I915_READ(pipeconf_reg); + pipe_bpc = temp & PIPE_BPC_MASK; /* XXX: When our outputs are all unaware of DPMS modes other than off * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. @@ -1524,6 +1528,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ temp = I915_READ(fdi_rx_reg); + /* + * make the BPC in FDI Rx be consistent with that in + * pipeconf reg. + */ + temp &= ~(0x7 << 16); + temp |= (pipe_bpc << 11); I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | FDI_SEL_PCDCLK | FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */ @@ -1666,6 +1676,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) /* enable PCH transcoder */ temp = I915_READ(transconf_reg); + /* + * make the BPC in transcoder be consistent with + * that in pipeconf reg. + */ + temp &= ~PIPE_BPC_MASK; + temp |= pipe_bpc; I915_WRITE(transconf_reg, temp | TRANS_ENABLE); I915_READ(transconf_reg); @@ -1745,6 +1761,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) I915_READ(fdi_tx_reg); temp = I915_READ(fdi_rx_reg); + /* BPC in FDI rx is consistent with that in pipeconf */ + temp &= ~(0x07 << 16); + temp |= (pipe_bpc << 11); I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE); I915_READ(fdi_rx_reg); @@ -1789,7 +1808,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) } } } - + temp = I915_READ(transconf_reg); + /* BPC in transcoder is consistent with that in pipeconf */ + temp &= ~PIPE_BPC_MASK; + temp |= pipe_bpc; + I915_WRITE(transconf_reg, temp); + I915_READ(transconf_reg); udelay(100); /* disable PCH DPLL */ -- cgit v1.2.3 From e5a95eb778690bc864eb330202d2c1b974caaeb4 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 4 Jan 2010 16:29:32 +0800 Subject: drm/i915: Select the correct BPC for LVDS on Ironlake Select the correct BPC for LVDS on Ironlake. If it is 18-bit LVDS panel, the BPC will be 6. When it is 24-bit LVDS panel, the BPC will 8. At the same time the BPC will be 8 when the output device is CRT/HDMI/DP. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 63e8e9fd679..5e2159b5992 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2993,6 +2993,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(pipeconf_reg); + temp &= ~PIPE_BPC_MASK; + if (is_lvds) { + int lvds_reg = I915_READ(PCH_LVDS); + /* the BPC will be 6 if it is 18-bit LVDS panel */ + if ((lvds_reg & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) + temp |= PIPE_8BPC; + else + temp |= PIPE_6BPC; + } else + temp |= PIPE_8BPC; + I915_WRITE(pipeconf_reg, temp); + I915_READ(pipeconf_reg); switch (temp & PIPE_BPC_MASK) { case PIPE_8BPC: -- cgit v1.2.3 From 4547668a050e7de3cd73a4c6736dfc2adebff67d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Thu, 31 Dec 2009 16:06:04 +0800 Subject: drm/i915: Add DP dpll limit on ironlake and use existing DPLL search function For some clocks, the old Ironlake DPLL calculator wold give m/n/p combinations that didn't match the spreadsheet of what HW validation tests. Instead, use the G4X DPLL calculator, which does a better job at it. So we use the intel_g4x_find_best_pll to calculate the DPLL for CRT/HDMI/LVDS on ironlake. At the same time to consider the dpll setting for display port, we add the display port DPLL limit on ironlake, which will directly use the function of intel_find_pll_ironlake_dp to get the corresponding dpll setting. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 116 +++++++++++++++-------------------- 1 file changed, 48 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5e2159b5992..002612fae71 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -262,6 +262,14 @@ struct intel_limit { #define IRONLAKE_P2_LVDS_FAST 7 /* double channel */ #define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ +#define IRONLAKE_P_DISPLAY_PORT_MIN 10 +#define IRONLAKE_P_DISPLAY_PORT_MAX 20 +#define IRONLAKE_P2_DISPLAY_PORT_FAST 10 +#define IRONLAKE_P2_DISPLAY_PORT_SLOW 10 +#define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0 +#define IRONLAKE_P1_DISPLAY_PORT_MIN 1 +#define IRONLAKE_P1_DISPLAY_PORT_MAX 2 + static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); @@ -271,9 +279,6 @@ intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); -static bool -intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); static bool intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, @@ -496,7 +501,7 @@ static const intel_limit_t intel_limits_ironlake_sdvo = { .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW, .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST }, - .find_pll = intel_ironlake_find_best_PLL, + .find_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_ironlake_lvds = { @@ -511,7 +516,30 @@ static const intel_limit_t intel_limits_ironlake_lvds = { .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, .p2_slow = IRONLAKE_P2_LVDS_SLOW, .p2_fast = IRONLAKE_P2_LVDS_FAST }, - .find_pll = intel_ironlake_find_best_PLL, + .find_pll = intel_g4x_find_best_PLL, +}; + +static const intel_limit_t intel_limits_ironlake_display_port = { + .dot = { .min = IRONLAKE_DOT_MIN, + .max = IRONLAKE_DOT_MAX }, + .vco = { .min = IRONLAKE_VCO_MIN, + .max = IRONLAKE_VCO_MAX}, + .n = { .min = IRONLAKE_N_MIN, + .max = IRONLAKE_N_MAX }, + .m = { .min = IRONLAKE_M_MIN, + .max = IRONLAKE_M_MAX }, + .m1 = { .min = IRONLAKE_M1_MIN, + .max = IRONLAKE_M1_MAX }, + .m2 = { .min = IRONLAKE_M2_MIN, + .max = IRONLAKE_M2_MAX }, + .p = { .min = IRONLAKE_P_DISPLAY_PORT_MIN, + .max = IRONLAKE_P_DISPLAY_PORT_MAX }, + .p1 = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN, + .max = IRONLAKE_P1_DISPLAY_PORT_MAX}, + .p2 = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT, + .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW, + .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST }, + .find_pll = intel_find_pll_ironlake_dp, }; static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) @@ -519,6 +547,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) limit = &intel_limits_ironlake_lvds; + else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + HAS_eDP) + limit = &intel_limits_ironlake_display_port; else limit = &intel_limits_ironlake_sdvo; @@ -791,7 +822,13 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, found = false; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == + int lvds_reg; + + if (IS_IRONLAKE(dev)) + lvds_reg = PCH_LVDS; + else + lvds_reg = LVDS; + if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) clock.p2 = limit->p2.p2_fast; else @@ -839,6 +876,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; intel_clock_t clock; + + /* return directly when it is eDP */ + if (HAS_eDP) + return true; + if (target < 200000) { clock.n = 1; clock.p1 = 2; @@ -857,68 +899,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, return true; } -static bool -intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) -{ - struct drm_device *dev = crtc->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - intel_clock_t clock; - int err_most = 47; - int err_min = 10000; - - /* eDP has only 2 clock choice, no n/m/p setting */ - if (HAS_eDP) - return true; - - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) - return intel_find_pll_ironlake_dp(limit, crtc, target, - refclk, best_clock); - - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) - clock.p2 = limit->p2.p2_fast; - else - clock.p2 = limit->p2.p2_slow; - } else { - if (target < limit->p2.dot_limit) - clock.p2 = limit->p2.p2_slow; - else - clock.p2 = limit->p2.p2_fast; - } - - memset(best_clock, 0, sizeof(*best_clock)); - for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { - /* based on hardware requriment prefer smaller n to precision */ - for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) { - /* based on hardware requirment prefere larger m1,m2 */ - for (clock.m1 = limit->m1.max; - clock.m1 >= limit->m1.min; clock.m1--) { - for (clock.m2 = limit->m2.max; - clock.m2 >= limit->m2.min; clock.m2--) { - int this_err; - - intel_clock(dev, refclk, &clock); - if (!intel_PLL_is_valid(crtc, &clock)) - continue; - this_err = abs((10000 - (target*10000/clock.dot))); - if (this_err < err_most) { - *best_clock = clock; - /* found on first matching */ - goto out; - } else if (this_err < err_min) { - *best_clock = clock; - err_min = this_err; - } - } - } - } - } -out: - return true; -} - /* DisplayPort has only two frequencies, 162MHz and 270MHz */ static bool intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, -- cgit v1.2.3 From 823f68fd646da6a39a9c0d3eb4c60d69dab5aa13 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 28 Dec 2009 13:23:36 +0800 Subject: drm/i915: remove full registers dump debug This one reverts 9e3a6d155ed0a7636b926a798dd7221ea107b274. As reported by http://bugzilla.kernel.org/show_bug.cgi?id=14485, this dump will cause hang problem on some machine. If something really needs this kind of full registers dump, that could be done within intel-gpu-tools. Cc: Ben Gamari Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_debugfs.c | 29 ----------------------------- 1 file changed, 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 463e8d0155c..9c9998c4dce 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -386,34 +386,6 @@ out: return 0; } -static int i915_registers_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; - drm_i915_private_t *dev_priv = dev->dev_private; - uint32_t reg; - -#define DUMP_RANGE(start, end) \ - for (reg=start; reg < end; reg += 4) \ - seq_printf(m, "%08x\t%08x\n", reg, I915_READ(reg)); - - DUMP_RANGE(0x00000, 0x00fff); /* VGA registers */ - DUMP_RANGE(0x02000, 0x02fff); /* instruction, memory, interrupt control registers */ - DUMP_RANGE(0x03000, 0x031ff); /* FENCE and PPGTT control registers */ - DUMP_RANGE(0x03200, 0x03fff); /* frame buffer compression registers */ - DUMP_RANGE(0x05000, 0x05fff); /* I/O control registers */ - DUMP_RANGE(0x06000, 0x06fff); /* clock control registers */ - DUMP_RANGE(0x07000, 0x07fff); /* 3D internal debug registers */ - DUMP_RANGE(0x07400, 0x088ff); /* GPE debug registers */ - DUMP_RANGE(0x0a000, 0x0afff); /* display palette registers */ - DUMP_RANGE(0x10000, 0x13fff); /* MMIO MCHBAR */ - DUMP_RANGE(0x30000, 0x3ffff); /* overlay registers */ - DUMP_RANGE(0x60000, 0x6ffff); /* display engine pipeline registers */ - DUMP_RANGE(0x70000, 0x72fff); /* display and cursor registers */ - DUMP_RANGE(0x73000, 0x73fff); /* performance counters */ - - return 0; -} - static int i915_wedged_open(struct inode *inode, struct file *filp) @@ -519,7 +491,6 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor) } static struct drm_info_list i915_debugfs_list[] = { - {"i915_regs", i915_registers_info, 0}, {"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}, -- cgit v1.2.3 From 4c425588e0d72c9c55024752b0f6e709c96787ff Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 6 Jan 2010 12:48:55 -0800 Subject: IB/mlx4: Initialize SRQ scatter entries when creating an SRQ As for memfree mthca hardware, ConnectX also requires SRQ WQE scatter entries to be initialized with the invalid L_Key at SRQ creation time. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/srq.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/srq.c b/drivers/infiniband/hw/mlx4/srq.c index d42565258fb..cf8085bcbd6 100644 --- a/drivers/infiniband/hw/mlx4/srq.c +++ b/drivers/infiniband/hw/mlx4/srq.c @@ -74,6 +74,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, struct mlx4_ib_dev *dev = to_mdev(pd->device); struct mlx4_ib_srq *srq; struct mlx4_wqe_srq_next_seg *next; + struct mlx4_wqe_data_seg *scatter; int desc_size; int buf_size; int err; @@ -149,6 +150,11 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd, next = get_wqe(srq, i); next->next_wqe_index = cpu_to_be16((i + 1) & (srq->msrq.max - 1)); + + for (scatter = (void *) (next + 1); + (void *) scatter < (void *) next + desc_size; + ++scatter) + scatter->lkey = cpu_to_be32(MLX4_INVALID_LKEY); } err = mlx4_mtt_init(dev->dev, srq->buf.npages, srq->buf.page_shift, -- cgit v1.2.3 From 2b946077423270f065013c45d78522a5fb9542ca Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Wed, 6 Jan 2010 12:51:30 -0800 Subject: IB/mlx4: Fix queue overflow check in post_recv In mlx4_ib_post_recv(), we should check the queue for overflow using recv_cq instead of send_cq (current code looks like a copy-and-paste mistake). Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 989555cee88..2a97c964b9e 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1752,7 +1752,7 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr, ind = qp->rq.head & (qp->rq.wqe_cnt - 1); for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.send_cq)) { + if (mlx4_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) { err = -ENOMEM; *bad_wr = wr; goto out; -- cgit v1.2.3 From b4f77264cd1a858ee09da8dba5a2711a649adbf3 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 6 Jan 2010 12:54:39 -0800 Subject: mlx4_core: Fix cleanup in __mlx4_init_one() error path If mlx4_init_port_info() fails, cleanup the initialized ports only. Signed-off-by: Eli Cohen Signed-off-by: Roland Dreier --- drivers/net/mlx4/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 291a505fd4f..3cf56d90d85 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -1174,7 +1174,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return 0; err_port: - for (port = 1; port <= dev->caps.num_ports; port++) + for (--port; port >= 1; --port) mlx4_cleanup_port_info(&priv->port[port]); mlx4_cleanup_mcg_table(dev); -- cgit v1.2.3 From fd4582a3999e03fa9eae315bf14c88fd32d44035 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 6 Jan 2010 13:16:30 -0800 Subject: IB/addr: Correct CONFIG_IPv6 to CONFIG_IPV6 Correct misspelled "CONFIG_IPv6" that was introduced in commit d14714df ("IB/addr: Fix IPv6 routing lookup"). The config variable should be all uppercase. Signed-off-by: Robert P. J. Day [ This was my fault when I munged the original patch. - Roland ] Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index fbdd7310600..cc9b5940fa9 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2083,7 +2083,7 @@ static int cma_get_port(struct rdma_id_private *id_priv) static int cma_check_linklocal(struct rdma_dev_addr *dev_addr, struct sockaddr *addr) { -#if defined(CONFIG_IPv6) || defined(CONFIG_IPV6_MODULE) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 *sin6; if (addr->sa_family != AF_INET6) -- cgit v1.2.3 From e6be8d9d17bd44061116f601fe2609b3ace7aa69 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:05 +0800 Subject: drm: remove address mask param for drm_pci_alloc() drm_pci_alloc() has input of address mask for setting pci dma mask on the device, which should be properly setup by drm driver. And leave it as a param for drm_pci_alloc() would cause confusion or mistake would corrupt the correct dma mask setting, as seen on intel hw which set wrong dma mask for hw status page. So remove it from drm_pci_alloc() function. Signed-off-by: Zhenyu Wang Signed-off-by: Dave Airlie --- drivers/gpu/drm/ati_pcigart.c | 10 ++++++++-- drivers/gpu/drm/drm_bufs.c | 4 ++-- drivers/gpu/drm/drm_pci.c | 8 +------- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index 628eae3e9b8..a1fce68e3bb 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c @@ -39,8 +39,7 @@ static int drm_ati_alloc_pcigart_table(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) { gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size, - PAGE_SIZE, - gart_info->table_mask); + PAGE_SIZE); if (gart_info->table_handle == NULL) return -ENOMEM; @@ -112,6 +111,13 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); + if (pci_set_dma_mask(dev->pdev, gart_info->table_mask)) { + DRM_ERROR("fail to set dma mask to 0x%Lx\n", + gart_info->table_mask); + ret = 1; + goto done; + } + ret = drm_ati_alloc_pcigart_table(dev, gart_info); if (ret) { DRM_ERROR("cannot allocate PCI GART page!\n"); diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 3d09e304f6f..8417cc4c43f 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -326,7 +326,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset, * As we're limiting the address to 2^32-1 (or less), * casting it down to 32 bits is no problem, but we * need to point to a 64bit variable first. */ - dmah = drm_pci_alloc(dev, map->size, map->size, 0xffffffffUL); + dmah = drm_pci_alloc(dev, map->size, map->size); if (!dmah) { kfree(map); return -ENOMEM; @@ -885,7 +885,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) while (entry->buf_count < count) { - dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000, 0xfffffffful); + dmah = drm_pci_alloc(dev, PAGE_SIZE << page_order, 0x1000); if (!dmah) { /* Set count correctly so we free the proper amount. */ diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index 577094fb199..e68ebf92fa2 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -47,8 +47,7 @@ /** * \brief Allocate a PCI consistent memory block, for DMA. */ -drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align, - dma_addr_t maxaddr) +drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align) { drm_dma_handle_t *dmah; #if 1 @@ -63,11 +62,6 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali if (align > size) return NULL; - if (pci_set_dma_mask(dev->pdev, maxaddr) != 0) { - DRM_ERROR("Setting pci dma mask failed\n"); - return NULL; - } - dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); if (!dmah) return NULL; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 701bfeac7f5..02607ed6139 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -123,7 +123,7 @@ static int i915_init_phys_hws(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; /* Program Hardware Status Page */ dev_priv->status_page_dmah = - drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); + drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE); if (!dev_priv->status_page_dmah) { DRM_ERROR("Can not allocate hardware status page\n"); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 917b8377ae2..c7f0cbec4e8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4708,7 +4708,7 @@ int i915_gem_init_phys_object(struct drm_device *dev, phys_obj->id = id; - phys_obj->handle = drm_pci_alloc(dev, size, 0, 0xffffffff); + phys_obj->handle = drm_pci_alloc(dev, size, 0); if (!phys_obj->handle) { ret = -ENOMEM; goto kfree_obj; -- cgit v1.2.3 From 69da301589b579f9619475e30cc449df9193410c Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 4 Jan 2010 17:53:06 -0500 Subject: drm/edid: Skip empty CVT codepoints Signed-off-by: Adam Jackson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5c9f79877cb..7d6ac22f5b2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -911,11 +911,15 @@ static int drm_cvt_modes(struct drm_connector *connector, struct drm_device *dev = connector->dev; struct cvt_timing *cvt; const int rates[] = { 60, 85, 75, 60, 50 }; + const u8 empty[3] = { 0, 0, 0 }; for (i = 0; i < 4; i++) { int uninitialized_var(width), height; cvt = &(timing->data.other_data.data.cvt[i]); + if (!memcmp(cvt->code, empty, 3)) + continue; + height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2; switch (cvt->code[1] & 0xc0) { case 0x00: -- cgit v1.2.3 From 8e10ee9a0da12c586d3397150e34a946507c23f3 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Mon, 4 Jan 2010 17:53:07 -0500 Subject: drm/edid: Fix CVT width/height decode Signed-off-by: Adam Jackson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7d6ac22f5b2..defcaf10846 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -920,18 +920,18 @@ static int drm_cvt_modes(struct drm_connector *connector, if (!memcmp(cvt->code, empty, 3)) continue; - height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2; - switch (cvt->code[1] & 0xc0) { + height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; + switch (cvt->code[1] & 0x0c) { case 0x00: width = height * 4 / 3; break; - case 0x40: + case 0x04: width = height * 16 / 9; break; - case 0x80: + case 0x08: width = height * 16 / 10; break; - case 0xc0: + case 0x0c: width = height * 15 / 9; break; } -- cgit v1.2.3 From e89a8c901ca94a47c0e0b2fb335623d810e37545 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 31 Dec 2009 13:06:29 +0100 Subject: drm/kms: Fix &&/|| confusion in drm_fb_helper_connector_parse_command_line() This always evaluates to true. Signed-off-by: Roel Kluin Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1b49fa055f4..100ee48760b 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -156,7 +156,7 @@ static bool drm_fb_helper_connector_parse_command_line(struct drm_connector *con force = DRM_FORCE_ON; break; case 'D': - if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) || + if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) && (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) force = DRM_FORCE_ON; else -- cgit v1.2.3 From 5eb226132f53d5ec36ce4e7ff9d6b49cceb50f3d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 6 Jan 2010 17:39:31 +0100 Subject: drm/radeon/kms: fix memory leak Stanse found a memory leak in radeon_master_create. master_priv is not freed/assigned on all paths. Fix that. Signed-off-by: Jiri Slaby Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 0b2f9c2ad2c..06123ba31d3 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -2145,6 +2145,7 @@ int radeon_master_create(struct drm_device *dev, struct drm_master *master) &master_priv->sarea); if (ret) { DRM_ERROR("SAREA setup failed\n"); + kfree(master_priv); return ret; } master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea); -- cgit v1.2.3 From d8a7f79246a447722bd90c2c4ba3ca068b2aa4c0 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:22:55 +1100 Subject: drm/radeon/radeon_connectors.c: add a NULL test before dereference The encoder variable can be NULL in this function so I believe it should be checked before dereference. Coverity CID: 13253 [airlied: extremely unlikely to happen] Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 20161567dbf..b82ae61d4d1 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -615,7 +615,7 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect ret = connector_status_connected; } } else { - if (radeon_connector->dac_load_detect) { + if (radeon_connector->dac_load_detect && encoder) { encoder_funcs = encoder->helper_private; ret = encoder_funcs->detect(encoder, connector); } -- cgit v1.2.3 From 3655d54af8dd85788c3e5088387469703a0f8f12 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:20:05 +1100 Subject: drm/radeon/radeon_fence.c: move a dereference below the NULL test If a NULL value is possible, the dereference should only occur after the NULL test. Coverity CID: 13334 Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_fence.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 4cdd8b4f754..8495d4e32e1 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -140,16 +140,15 @@ int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence) bool radeon_fence_signaled(struct radeon_fence *fence) { - struct radeon_device *rdev = fence->rdev; unsigned long irq_flags; bool signaled = false; - if (rdev->gpu_lockup) { + if (!fence) return true; - } - if (fence == NULL) { + + if (fence->rdev->gpu_lockup) return true; - } + write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags); signaled = fence->signaled; /* if we are shuting down report all fence as signaled */ -- cgit v1.2.3 From 875c186620e017e62b773c93e46af21bb704fe6b Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:18:30 +1100 Subject: drm/radeon/radeon_device.c: move a dereference below a NULL test If a NULL value is possible, the dereference should only occur after the NULL test. Coverity CID: 13335 Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 7c6848096bc..0c51f8e4661 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -733,16 +733,18 @@ void radeon_device_fini(struct radeon_device *rdev) */ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) { - struct radeon_device *rdev = dev->dev_private; + struct radeon_device *rdev; struct drm_crtc *crtc; int r; - if (dev == NULL || rdev == NULL) { + if (dev == NULL || dev->dev_private == NULL) { return -ENODEV; } if (state.event == PM_EVENT_PRETHAW) { return 0; } + rdev = dev->dev_private; + /* unpin the front buffers */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); -- cgit v1.2.3 From 65aa2f4e8d85b6145ef4834f440a63ab68bd7443 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Wed, 30 Dec 2009 12:16:35 +1100 Subject: gpu/drm/radeon/radeon_irq.c: move a dereference below a NULL test If a NULL value is possible, the dereference should only occur after the NULL test. Coverity CID: 13338 Signed-off-by: Darren Jenkins Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_irq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index b79ecc4a7cc..2f349a30019 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -289,16 +289,16 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr drm_radeon_irq_emit_t *emit = data; int result; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return -EINVAL; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) + return -EINVAL; + + LOCK_TEST_WITH_RETURN(dev, file_priv); + result = radeon_emit_irq(dev); if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { -- cgit v1.2.3 From 43b19f161c7a9941e3aa7db0e3ee19b93980e3d7 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Mon, 28 Dec 2009 22:53:05 +0100 Subject: drm/radeon/kms: rs600: use correct mask for SW interrupt The mask happens to be the same, but the IH is reading the status, not the not the control register. Signed-off-by: Luca Tettamanti Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/rs600.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 4f8ea426057..4245218e954 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -396,7 +396,7 @@ int rs600_irq_process(struct radeon_device *rdev) } while (status || r500_disp_int) { /* SW interrupt */ - if (G_000040_SW_INT_EN(status)) + if (G_000044_SW_INT(status)) radeon_fence_process(rdev); /* Vertical blank interrupts */ if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) -- cgit v1.2.3 From e4e6efd2df4b5754bd519b516207eb723d1f17df Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 7 Jan 2010 01:52:39 -0800 Subject: Input: psmouse - fix Synaptics detection when protocol is disabled For configurations where Synaptics hardware is present but the Synaptics extensions support is not compiled in, the mouse is reprobed and a new device is allocated on every suspend/resume. During probe, psmouse_switch_protocol() calls psmouse_extensions() with set_properties=1. This calls the dummy synaptics_init() which returns an error code, instructing us not to use the synaptics extensions. During resume, psmouse_reconnect() calls psmouse_extensions() with set_properties=0, in which case call to synaptics_init() is bypassed and PSMOUSE_SYNAPTICS is returned. Since the result is different from previous attempt psmouse_reconnect() fails and full re-probe happens. Fix this by tweaking the set_properties=0 codepath in psmouse_extensions() to be more careful about offering PSMOUSE_SYNAPTICS extensions. Signed-off-by: Daniel Drake Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 9 ++++++++- drivers/input/mouse/synaptics.c | 10 ++++++++++ drivers/input/mouse/synaptics.h | 1 + 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d59e18b24ed..cabf4e1caac 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -627,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse, synaptics_hardware = true; if (max_proto > PSMOUSE_IMEX) { - if (!set_properties || synaptics_init(psmouse) == 0) +/* + * Try activating protocol, but check if support is enabled first, since + * we try detecting Synaptics even when protocol is disabled. + */ + if (synaptics_supported() && + (!set_properties || synaptics_init(psmouse) == 0)) { return PSMOUSE_SYNAPTICS; + } + /* * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). * Unfortunately Logitech/Genius probes confuse some firmware versions so diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 05689e73219..d3f5243fa09 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -743,6 +743,11 @@ int synaptics_init(struct psmouse *psmouse) return -1; } +bool synaptics_supported(void) +{ + return true; +} + #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ void __init synaptics_module_init(void) @@ -754,5 +759,10 @@ int synaptics_init(struct psmouse *psmouse) return -ENOSYS; } +bool synaptics_supported(void) +{ + return false; +} + #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 838e7f2c9b3..f0f40a331dc 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -109,5 +109,6 @@ void synaptics_module_init(void); int synaptics_detect(struct psmouse *psmouse, bool set_properties); int synaptics_init(struct psmouse *psmouse); void synaptics_reset(struct psmouse *psmouse); +bool synaptics_supported(void); #endif /* _SYNAPTICS_H */ -- cgit v1.2.3 From 36bfc7e2100ab3f9891bb779c36d5e685f253509 Mon Sep 17 00:00:00 2001 From: Lars Ellenberg Date: Tue, 5 Jan 2010 19:33:54 +0100 Subject: drbd: check on CONFIG_LBDAF, not LBD It is called LBDAF since 2.6.31. impact: without this change, on 32bit, DRBD would wrongly claim to only support 2TiB devices. Signed-off-by: Lars Ellenberg Signed-off-by: Philipp Reisner --- drivers/block/drbd/drbd_int.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c9755876343..79d8e22c4d0 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1275,7 +1275,7 @@ struct bm_extent { #if DRBD_MAX_SECTORS_BM < DRBD_MAX_SECTORS_32 #define DRBD_MAX_SECTORS DRBD_MAX_SECTORS_BM #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_BM -#elif !defined(CONFIG_LBD) && BITS_PER_LONG == 32 +#elif !defined(CONFIG_LBDAF) && BITS_PER_LONG == 32 #define DRBD_MAX_SECTORS DRBD_MAX_SECTORS_32 #define DRBD_MAX_SECTORS_FLEX DRBD_MAX_SECTORS_32 #else -- cgit v1.2.3 From 8fcc501831aa5b37a4a5a8cd9dc965be3cacc599 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 28 Dec 2009 13:15:20 +0800 Subject: drm/i915: disable TV hotplug status check As we removed TV hotplug, don't check its status ever. Reviewed-by: Adam Jackson Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_tv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 1d5b9b7b033..552ec110b74 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1840,8 +1840,6 @@ intel_tv_init(struct drm_device *dev) drm_connector_attach_property(connector, dev->mode_config.tv_bottom_margin_property, tv_priv->margin[TV_MARGIN_BOTTOM]); - - dev_priv->hotplug_supported_mask |= TV_HOTPLUG_INT_STATUS; out: drm_sysfs_connector_add(connector); } -- cgit v1.2.3 From 40f33a92100f4d9b6e85ad642100cfe42d7ff57d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 13:30:36 +0800 Subject: drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list The HP comaq nx9020/Samsung SX20S laptop always report that the LID status is closed and we can't use it reliabily for LVDS detection. So add the two boxes into the quirk list. http://bugzilla.kernel.org/show_bug.cgi?id=14957 http://bugzilla.kernel.org/show_bug.cgi?id=14554 Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_lvds.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f4b4aa242df..5041590dfdc 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -601,6 +601,20 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, /* Some lid devices report incorrect lid status, assume they're connected */ static const struct dmi_system_id bad_lid_status[] = { + { + .ident = "Compaq nx9020", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_BOARD_NAME, "3084"), + }, + }, + { + .ident = "Samsung SX20S", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_BOARD_NAME, "SX20S"), + }, + }, { .ident = "Aspire One", .matches = { -- cgit v1.2.3 From ddc9003c357d1ce10be6ec91bdb8df8ea836087d Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 22:05:56 +0800 Subject: drm/i915: Use find_pll function to calculate DPLL setting for LVDS downclock For any given clock we can use the find_pll to get the corresponding DPLL setting. It is unnecessary to use the find_reduce_pll callback function to calculate the DPLL parameter for LVDS downclock in order to get the same divider factor(P) for the normal and downclock. In theory when the LVDS downclock is supported by LVDS panel, we should get the same DPLL divider factor(P) for the normal clock and reduced downclock. If we get the diferent divider factor(P) for normal clock and reduced downclock, it means that the found downclock is incorrect and should be discarded. So we should use find_pll callback to calculate the DPLL parameter for the LVDS reduced downclock as for the normal clock. Then we can do the cleanup about find_reduced_pll. Signed-off-by: Zhao Yakui cc: Jesse Barnes cc: Matthew Garrett Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 61 ++---------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 002612fae71..0cf44d6e9de 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -70,8 +70,6 @@ struct intel_limit { intel_p2_t p2; bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, int, int, intel_clock_t *); - bool (* find_reduced_pll)(const intel_limit_t *, struct drm_crtc *, - int, int, intel_clock_t *); }; #define I8XX_DOT_MIN 25000 @@ -274,9 +272,6 @@ static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); static bool -intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); -static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock); @@ -299,7 +294,6 @@ static const intel_limit_t intel_limits_i8xx_dvo = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i8xx_lvds = { @@ -314,7 +308,6 @@ static const intel_limit_t intel_limits_i8xx_lvds = { .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i9xx_sdvo = { @@ -329,7 +322,6 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_i9xx_lvds = { @@ -347,7 +339,6 @@ static const intel_limit_t intel_limits_i9xx_lvds = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; /* below parameter and function is for G4X Chipset Family*/ @@ -365,7 +356,6 @@ static const intel_limit_t intel_limits_g4x_sdvo = { .p2_fast = G4X_P2_SDVO_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_hdmi = { @@ -382,7 +372,6 @@ static const intel_limit_t intel_limits_g4x_hdmi = { .p2_fast = G4X_P2_HDMI_DAC_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_single_channel_lvds = { @@ -407,7 +396,6 @@ static const intel_limit_t intel_limits_g4x_single_channel_lvds = { .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { @@ -432,7 +420,6 @@ static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST }, .find_pll = intel_g4x_find_best_PLL, - .find_reduced_pll = intel_g4x_find_best_PLL, }; static const intel_limit_t intel_limits_g4x_display_port = { @@ -470,7 +457,6 @@ static const intel_limit_t intel_limits_pineview_sdvo = { .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_pineview_lvds = { @@ -486,7 +472,6 @@ static const intel_limit_t intel_limits_pineview_lvds = { .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, .find_pll = intel_find_best_PLL, - .find_reduced_pll = intel_find_best_reduced_PLL, }; static const intel_limit_t intel_limits_ironlake_sdvo = { @@ -768,46 +753,6 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, return (err != target); } - -static bool -intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) - -{ - struct drm_device *dev = crtc->dev; - intel_clock_t clock; - int err = target; - bool found = false; - - memcpy(&clock, best_clock, sizeof(intel_clock_t)); - - for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { - for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max; clock.m2++) { - /* m1 is always 0 in Pineview */ - if (clock.m2 >= clock.m1 && !IS_PINEVIEW(dev)) - break; - for (clock.n = limit->n.min; clock.n <= limit->n.max; - clock.n++) { - int this_err; - - intel_clock(dev, refclk, &clock); - - if (!intel_PLL_is_valid(crtc, &clock)) - continue; - - this_err = abs(clock.dot - target); - if (this_err < err) { - *best_clock = clock; - err = this_err; - found = true; - } - } - } - } - - return found; -} - static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, intel_clock_t *best_clock) @@ -2910,10 +2855,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return -EINVAL; } - if (is_lvds && limit->find_reduced_pll && - dev_priv->lvds_downclock_avail) { - memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); - has_reduced_clock = limit->find_reduced_pll(limit, crtc, + if (is_lvds && dev_priv->lvds_downclock_avail) { + has_reduced_clock = limit->find_pll(limit, crtc, dev_priv->lvds_downclock, refclk, &reduced_clock); -- cgit v1.2.3 From a59e385eacd920222756a23c113444fe3063cf81 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 22:05:57 +0800 Subject: drm/i915: Fix Ironlake M/N/P ranges to match the spec Without this fix, some modes couldn't find appropriate clocks. Signed-off-by: Zhao Yakui Signed-off-by: Eric Anholt Tested-by: Matthew Garrett --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0cf44d6e9de..42e8c031c2c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -241,11 +241,11 @@ struct intel_limit { #define IRONLAKE_VCO_MIN 1760000 #define IRONLAKE_VCO_MAX 3510000 #define IRONLAKE_N_MIN 1 -#define IRONLAKE_N_MAX 5 +#define IRONLAKE_N_MAX 6 #define IRONLAKE_M_MIN 79 -#define IRONLAKE_M_MAX 118 +#define IRONLAKE_M_MAX 127 #define IRONLAKE_M1_MIN 12 -#define IRONLAKE_M1_MAX 23 +#define IRONLAKE_M1_MAX 22 #define IRONLAKE_M2_MIN 5 #define IRONLAKE_M2_MAX 9 #define IRONLAKE_P_SDVO_DAC_MIN 5 -- cgit v1.2.3 From a5899fcc189e9357873ddf26d5e6e7e6ff84c2f4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 7 Jan 2010 14:19:47 -0500 Subject: drm/radeon/kms: fix typo in atom connector type handling Also remove the problematic enums that were unused remnants from the ddx. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 10 +++++----- drivers/gpu/drm/radeon/radeon_mode.h | 26 -------------------------- 2 files changed, 5 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index ccba95f83d1..844c513f724 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -604,13 +604,13 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) else return ATOM_ENCODER_MODE_DVI; break; - case CONNECTOR_DVI_A: - case CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_DVIA: + case DRM_MODE_CONNECTOR_VGA: return ATOM_ENCODER_MODE_CRT; break; - case CONNECTOR_STV: - case CONNECTOR_CTV: - case CONNECTOR_DIN: + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_9PinDIN: /* fix me */ return ATOM_ENCODER_MODE_TV; /*return ATOM_ENCODER_MODE_CV;*/ diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 402369db5ba..91cb041cb40 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -46,32 +46,6 @@ struct radeon_device; #define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base) #define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base) -enum radeon_connector_type { - CONNECTOR_NONE, - CONNECTOR_VGA, - CONNECTOR_DVI_I, - CONNECTOR_DVI_D, - CONNECTOR_DVI_A, - CONNECTOR_STV, - CONNECTOR_CTV, - CONNECTOR_LVDS, - CONNECTOR_DIGITAL, - CONNECTOR_SCART, - CONNECTOR_HDMI_TYPE_A, - CONNECTOR_HDMI_TYPE_B, - CONNECTOR_0XC, - CONNECTOR_0XD, - CONNECTOR_DIN, - CONNECTOR_DISPLAY_PORT, - CONNECTOR_UNSUPPORTED -}; - -enum radeon_dvi_type { - DVI_AUTO, - DVI_DIGITAL, - DVI_ANALOG -}; - enum radeon_rmx_type { RMX_OFF, RMX_FULL, -- cgit v1.2.3 From a7bc115fffb69a55cf2c332567ea6908d9026f22 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 7 Jan 2010 11:35:48 -0500 Subject: drm/radeon/kms: whitespace changes to ObjectID.h Makes it easier to keep in sync with ddx and the upstream AMD versions. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/ObjectID.h | 678 +++++++++++++++++--------------------- 1 file changed, 309 insertions(+), 369 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ObjectID.h b/drivers/gpu/drm/radeon/ObjectID.h index 6d0183c61d3..f1f18a48cf6 100644 --- a/drivers/gpu/drm/radeon/ObjectID.h +++ b/drivers/gpu/drm/radeon/ObjectID.h @@ -1,5 +1,5 @@ /* -* Copyright 2006-2007 Advanced Micro Devices, Inc. +* Copyright 2006-2007 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -41,14 +41,14 @@ /****************************************************/ /* Encoder Object ID Definition */ /****************************************************/ -#define ENCODER_OBJECT_ID_NONE 0x00 +#define ENCODER_OBJECT_ID_NONE 0x00 /* Radeon Class Display Hardware */ #define ENCODER_OBJECT_ID_INTERNAL_LVDS 0x01 #define ENCODER_OBJECT_ID_INTERNAL_TMDS1 0x02 #define ENCODER_OBJECT_ID_INTERNAL_TMDS2 0x03 #define ENCODER_OBJECT_ID_INTERNAL_DAC1 0x04 -#define ENCODER_OBJECT_ID_INTERNAL_DAC2 0x05 /* TV/CV DAC */ +#define ENCODER_OBJECT_ID_INTERNAL_DAC2 0x05 /* TV/CV DAC */ #define ENCODER_OBJECT_ID_INTERNAL_SDVOA 0x06 #define ENCODER_OBJECT_ID_INTERNAL_SDVOB 0x07 @@ -56,11 +56,11 @@ #define ENCODER_OBJECT_ID_SI170B 0x08 #define ENCODER_OBJECT_ID_CH7303 0x09 #define ENCODER_OBJECT_ID_CH7301 0x0A -#define ENCODER_OBJECT_ID_INTERNAL_DVO1 0x0B /* This belongs to Radeon Class Display Hardware */ +#define ENCODER_OBJECT_ID_INTERNAL_DVO1 0x0B /* This belongs to Radeon Class Display Hardware */ #define ENCODER_OBJECT_ID_EXTERNAL_SDVOA 0x0C #define ENCODER_OBJECT_ID_EXTERNAL_SDVOB 0x0D #define ENCODER_OBJECT_ID_TITFP513 0x0E -#define ENCODER_OBJECT_ID_INTERNAL_LVTM1 0x0F /* not used for Radeon */ +#define ENCODER_OBJECT_ID_INTERNAL_LVTM1 0x0F /* not used for Radeon */ #define ENCODER_OBJECT_ID_VT1623 0x10 #define ENCODER_OBJECT_ID_HDMI_SI1930 0x11 #define ENCODER_OBJECT_ID_HDMI_INTERNAL 0x12 @@ -68,9 +68,9 @@ #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 0x15 -#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 0x16 /* Shared with CV/TV and CRT */ -#define ENCODER_OBJECT_ID_SI178 0X17 /* External TMDS (dual link, no HDCP.) */ -#define ENCODER_OBJECT_ID_MVPU_FPGA 0x18 /* MVPU FPGA chip */ +#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 0x16 /* Shared with CV/TV and CRT */ +#define ENCODER_OBJECT_ID_SI178 0X17 /* External TMDS (dual link, no HDCP.) */ +#define ENCODER_OBJECT_ID_MVPU_FPGA 0x18 /* MVPU FPGA chip */ #define ENCODER_OBJECT_ID_INTERNAL_DDI 0x19 #define ENCODER_OBJECT_ID_VT1625 0x1A #define ENCODER_OBJECT_ID_HDMI_SI1932 0x1B @@ -86,7 +86,7 @@ /****************************************************/ /* Connector Object ID Definition */ /****************************************************/ -#define CONNECTOR_OBJECT_ID_NONE 0x00 +#define CONNECTOR_OBJECT_ID_NONE 0x00 #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I 0x01 #define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I 0x02 #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D 0x03 @@ -96,7 +96,7 @@ #define CONNECTOR_OBJECT_ID_SVIDEO 0x07 #define CONNECTOR_OBJECT_ID_YPbPr 0x08 #define CONNECTOR_OBJECT_ID_D_CONNECTOR 0x09 -#define CONNECTOR_OBJECT_ID_9PIN_DIN 0x0A /* Supports both CV & TV */ +#define CONNECTOR_OBJECT_ID_9PIN_DIN 0x0A /* Supports both CV & TV */ #define CONNECTOR_OBJECT_ID_SCART 0x0B #define CONNECTOR_OBJECT_ID_HDMI_TYPE_A 0x0C #define CONNECTOR_OBJECT_ID_HDMI_TYPE_B 0x0D @@ -116,7 +116,7 @@ #define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL 0x01 /****************************************************/ -/* Graphics Object ENUM ID Definition */ +// Graphics Object ENUM ID Definition */ /****************************************************/ #define GRAPH_OBJECT_ENUM_ID1 0x01 #define GRAPH_OBJECT_ENUM_ID2 0x02 @@ -133,35 +133,35 @@ #define RESERVED1_ID_MASK 0x0800 #define OBJECT_TYPE_MASK 0x7000 #define RESERVED2_ID_MASK 0x8000 - + #define OBJECT_ID_SHIFT 0x00 #define ENUM_ID_SHIFT 0x08 #define OBJECT_TYPE_SHIFT 0x0C + /****************************************************/ /* Graphics Object family definition */ /****************************************************/ -#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) \ - (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \ - GRAPHICS_OBJECT_ID << OBJECT_ID_SHIFT) +#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \ + GRAPHICS_OBJECT_ID << OBJECT_ID_SHIFT) /****************************************************/ /* GPU Object ID definition - Shared with BIOS */ /****************************************************/ -#define GPU_ENUM_ID1 (GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT) +#define GPU_ENUM_ID1 ( GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT) /****************************************************/ /* Encoder Object ID definition - Shared with BIOS */ /****************************************************/ /* -#define ENCODER_INTERNAL_LVDS_ENUM_ID1 0x2101 +#define ENCODER_INTERNAL_LVDS_ENUM_ID1 0x2101 #define ENCODER_INTERNAL_TMDS1_ENUM_ID1 0x2102 #define ENCODER_INTERNAL_TMDS2_ENUM_ID1 0x2103 #define ENCODER_INTERNAL_DAC1_ENUM_ID1 0x2104 #define ENCODER_INTERNAL_DAC2_ENUM_ID1 0x2105 #define ENCODER_INTERNAL_SDVOA_ENUM_ID1 0x2106 #define ENCODER_INTERNAL_SDVOB_ENUM_ID1 0x2107 -#define ENCODER_SIL170B_ENUM_ID1 0x2108 +#define ENCODER_SIL170B_ENUM_ID1 0x2108 #define ENCODER_CH7303_ENUM_ID1 0x2109 #define ENCODER_CH7301_ENUM_ID1 0x210A #define ENCODER_INTERNAL_DVO1_ENUM_ID1 0x210B @@ -175,8 +175,8 @@ #define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 0x2113 #define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 0x2114 #define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 0x2115 -#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 0x2116 -#define ENCODER_SI178_ENUM_ID1 0x2117 +#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 0x2116 +#define ENCODER_SI178_ENUM_ID1 0x2117 #define ENCODER_MVPU_FPGA_ENUM_ID1 0x2118 #define ENCODER_INTERNAL_DDI_ENUM_ID1 0x2119 #define ENCODER_VT1625_ENUM_ID1 0x211A @@ -185,205 +185,169 @@ #define ENCODER_DP_DP501_ENUM_ID1 0x211D #define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 0x211E */ -#define ENCODER_INTERNAL_LVDS_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_DAC1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_DAC2_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT) - -#define ENCODER_SIL170B_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT) - -#define ENCODER_CH7303_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT) - -#define ENCODER_CH7301_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_DVO1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT) - -#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) - -#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) - -#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT) - -#define ENCODER_TITFP513_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT) - -#define ENCODER_VT1623_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT) - -#define ENCODER_HDMI_SI1930_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT) - -#define ENCODER_HDMI_INTERNAL_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) /* Shared with CV/TV and CRT */ - -#define ENCODER_SI178_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT) - -#define ENCODER_MVPU_FPGA_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_DDI_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT) - -#define ENCODER_VT1625_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT) - -#define ENCODER_HDMI_SI1932_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT) - -#define ENCODER_DP_DP501_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT) - -#define ENCODER_DP_AN9801_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) - -#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) - -#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT) +#define ENCODER_INTERNAL_LVDS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DAC1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DAC2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT) + +#define ENCODER_SIL170B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT) + +#define ENCODER_CH7303_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT) + +#define ENCODER_CH7301_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DVO1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT) + +#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) + +#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) + + +#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT) + + +#define ENCODER_TITFP513_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT) + +#define ENCODER_VT1623_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT) + +#define ENCODER_HDMI_SI1930_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT) + +#define ENCODER_HDMI_INTERNAL_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) + + +#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) + + +#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) // Shared with CV/TV and CRT + +#define ENCODER_SI178_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT) + +#define ENCODER_MVPU_FPGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_DDI_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT) + +#define ENCODER_VT1625_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT) + +#define ENCODER_HDMI_SI1932_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT) + +#define ENCODER_DP_DP501_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT) + +#define ENCODER_DP_AN9801_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) + +#define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) + +#define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT) /****************************************************/ /* Connector Object ID definition - Shared with BIOS */ @@ -406,158 +370,129 @@ #define CONNECTOR_7PIN_DIN_ENUM_ID1 0x310F #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 0x3110 */ -#define CONNECTOR_LVDS_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) - -#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) - -#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) - -#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) - -#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) - -#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) - -#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) - -#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) - -#define CONNECTOR_VGA_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) - -#define CONNECTOR_VGA_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) - -#define CONNECTOR_COMPOSITE_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) - -#define CONNECTOR_SVIDEO_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) - -#define CONNECTOR_YPbPr_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) - -#define CONNECTOR_D_CONNECTOR_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) - -#define CONNECTOR_9PIN_DIN_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) - -#define CONNECTOR_SCART_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) - -#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) - -#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) - -#define CONNECTOR_7PIN_DIN_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) - -#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) - -#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) - -#define CONNECTOR_CROSSFIRE_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) - -#define CONNECTOR_CROSSFIRE_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) - -#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) - -#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) - -#define CONNECTOR_DISPLAYPORT_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) - -#define CONNECTOR_DISPLAYPORT_ENUM_ID2 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) - -#define CONNECTOR_DISPLAYPORT_ENUM_ID3 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) - -#define CONNECTOR_DISPLAYPORT_ENUM_ID4 \ - (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ - CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) +#define CONNECTOR_LVDS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) + +#define CONNECTOR_VGA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) + +#define CONNECTOR_COMPOSITE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) + +#define CONNECTOR_SVIDEO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) + +#define CONNECTOR_YPbPr_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) + +#define CONNECTOR_D_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_9PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) + +#define CONNECTOR_SCART_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) + +#define CONNECTOR_7PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) + +#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) + +#define CONNECTOR_CROSSFIRE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) + +#define CONNECTOR_CROSSFIRE_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) + + +#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) + +#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) /****************************************************/ /* Router Object ID definition - Shared with BIOS */ /****************************************************/ -#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 \ - (GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\ - GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ - ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT) +#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT) /* deleted */ @@ -567,6 +502,7 @@ #define GRAPHICS_OBJECT_CAP_I2C 0x00000001L #define GRAPHICS_OBJECT_CAP_TABLE_ID 0x00000002L + #define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID 0x01 #define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID 0x02 #define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID 0x03 @@ -575,4 +511,8 @@ #pragma pack() #endif -#endif /*GRAPHICTYPE */ +#endif /*GRAPHICTYPE */ + + + + -- cgit v1.2.3 From f0f480adcb6c44e76186c6d3036e06ed7e7e0202 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 7 Jan 2010 11:39:07 -0500 Subject: drm/radeon/kms: pull in the latest upstream ObjectID.h changes Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/ObjectID.h | 127 +++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/ObjectID.h b/drivers/gpu/drm/radeon/ObjectID.h index f1f18a48cf6..c714179d1bf 100644 --- a/drivers/gpu/drm/radeon/ObjectID.h +++ b/drivers/gpu/drm/radeon/ObjectID.h @@ -106,6 +106,8 @@ #define CONNECTOR_OBJECT_ID_CROSSFIRE 0x11 #define CONNECTOR_OBJECT_ID_HARDCODE_DVI 0x12 #define CONNECTOR_OBJECT_ID_DISPLAYPORT 0x13 +#define CONNECTOR_OBJECT_ID_eDP 0x14 +#define CONNECTOR_OBJECT_ID_MXM 0x15 /* deleted */ @@ -116,7 +118,15 @@ #define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL 0x01 /****************************************************/ -// Graphics Object ENUM ID Definition */ +/* Generic Object ID Definition */ +/****************************************************/ +#define GENERIC_OBJECT_ID_NONE 0x00 +#define GENERIC_OBJECT_ID_GLSYNC 0x01 +#define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE 0x02 +#define GENERIC_OBJECT_ID_MXM_OPM 0x03 + +/****************************************************/ +/* Graphics Object ENUM ID Definition */ /****************************************************/ #define GRAPH_OBJECT_ENUM_ID1 0x01 #define GRAPH_OBJECT_ENUM_ID2 0x02 @@ -124,6 +134,7 @@ #define GRAPH_OBJECT_ENUM_ID4 0x04 #define GRAPH_OBJECT_ENUM_ID5 0x05 #define GRAPH_OBJECT_ENUM_ID6 0x06 +#define GRAPH_OBJECT_ENUM_ID7 0x07 /****************************************************/ /* Graphics Object ID Bit definition */ @@ -374,6 +385,18 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) +#define CONNECTOR_LVDS_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) + +#define CONNECTOR_eDP_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT) + +#define CONNECTOR_eDP_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_eDP << OBJECT_ID_SHIFT) + #define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) @@ -402,6 +425,14 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) + #define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) @@ -414,37 +445,76 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) +#define CONNECTOR_COMPOSITE_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) + #define CONNECTOR_SVIDEO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) +#define CONNECTOR_SVIDEO_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) + #define CONNECTOR_YPbPr_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) +#define CONNECTOR_YPbPr_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) + #define CONNECTOR_D_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) +#define CONNECTOR_D_CONNECTOR_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) + #define CONNECTOR_9PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) +#define CONNECTOR_9PIN_DIN_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) + #define CONNECTOR_SCART_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) +#define CONNECTOR_SCART_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) + #define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + +#define CONNECTOR_HDMI_TYPE_A_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) + #define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) +#define CONNECTOR_HDMI_TYPE_B_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) + #define CONNECTOR_7PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) +#define CONNECTOR_7PIN_DIN_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ @@ -487,6 +557,42 @@ GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) +#define CONNECTOR_DISPLAYPORT_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_DISPLAYPORT_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) + +#define CONNECTOR_MXM_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_A + +#define CONNECTOR_MXM_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_B + +#define CONNECTOR_MXM_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_C + +#define CONNECTOR_MXM_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DP_D + +#define CONNECTOR_MXM_ENUM_ID5 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID5 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_LVDS_TXxx + +#define CONNECTOR_MXM_ENUM_ID6 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID6 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_LVDS_UXxx + +#define CONNECTOR_MXM_ENUM_ID7 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DAC + /****************************************************/ /* Router Object ID definition - Shared with BIOS */ /****************************************************/ @@ -496,6 +602,25 @@ /* deleted */ +/****************************************************/ +/* Generic Object ID definition - Shared with BIOS */ +/****************************************************/ +#define GENERICOBJECT_GLSYNC_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_GLSYNC << OBJECT_ID_SHIFT) + +#define GENERICOBJECT_PX2_NON_DRIVABLE_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT) + +#define GENERICOBJECT_PX2_NON_DRIVABLE_ID2 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_PX2_NON_DRIVABLE<< OBJECT_ID_SHIFT) + +#define GENERICOBJECT_MXM_OPM_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT) + /****************************************************/ /* Object Cap definition - Shared with BIOS */ /****************************************************/ -- cgit v1.2.3 From 7970e677accb676f15e11468c60cb93ae477a513 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 7 Jan 2010 13:47:47 -0500 Subject: drm: Add eDP connector type Add a new connector type for eDP (embedded displayport) eDP is more or less the same as DP but there are some cases when you might want to handle it separately. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4a7bbdbedfc..fa19c2b9820 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -158,6 +158,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 }, { DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 }, { DRM_MODE_CONNECTOR_TV, "TV", 0 }, + { DRM_MODE_CONNECTOR_eDP, "Embedded DisplayPort", 0 }, }; static struct drm_prop_enum_list drm_encoder_enum_list[] = -- cgit v1.2.3 From 196c58d21fc47fbabab6a98e23e5a6335f717e44 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 7 Jan 2010 14:22:32 -0500 Subject: drm/radeon/kms: add support for eDP (embedded DisplayPort) This is displayport used for internal connections such as laptop panels and systems with integrated monitors. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_dp.c | 6 ++++-- drivers/gpu/drm/radeon/radeon_atombios.c | 4 +++- drivers/gpu/drm/radeon/radeon_connectors.c | 23 +++++++++++++++++------ drivers/gpu/drm/radeon/radeon_display.c | 7 +++++-- drivers/gpu/drm/radeon/radeon_encoders.c | 4 +++- 5 files changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 0d63c4436e7..3eb0ca5b3d7 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -468,7 +468,8 @@ void radeon_dp_set_link_config(struct drm_connector *connector, struct radeon_connector *radeon_connector; struct radeon_connector_atom_dig *dig_connector; - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) || + (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) return; radeon_connector = to_radeon_connector(connector); @@ -582,7 +583,8 @@ void dp_link_train(struct drm_encoder *encoder, u8 train_set[4]; int i; - if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) + if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) || + (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) return; if (!radeon_encoder->enc_priv) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 41dd8ebff21..18340354011 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -346,7 +346,9 @@ const int object_connector_convert[] = { DRM_MODE_CONNECTOR_Unknown, DRM_MODE_CONNECTOR_Unknown, DRM_MODE_CONNECTOR_Unknown, - DRM_MODE_CONNECTOR_DisplayPort + DRM_MODE_CONNECTOR_DisplayPort, + DRM_MODE_CONNECTOR_eDP, + DRM_MODE_CONNECTOR_Unknown }; bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index b82ae61d4d1..9da10dd5df8 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -49,8 +49,10 @@ void radeon_connector_hotplug(struct drm_connector *connector) if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); - if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - if (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + if ((connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (connector->connector_type == DRM_MODE_CONNECTOR_eDP)) { + if ((radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (radeon_dp_getsinktype(radeon_connector) == CONNECTOR_OBJECT_ID_eDP)) { if (radeon_dp_needs_link_train(radeon_connector)) { if (connector->encoder) dp_link_train(connector->encoder, connector); @@ -967,7 +969,8 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto } sink_type = radeon_dp_getsinktype(radeon_connector); - if (sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + 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; ret = connector_status_connected; @@ -992,7 +995,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector, /* XXX check mode bandwidth */ - if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) + if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return radeon_dp_mode_valid_helper(radeon_connector, mode); else return MODE_OK; @@ -1145,6 +1149,7 @@ radeon_add_atom_connector(struct drm_device *dev, subpixel_order = SubPixelHorizontalRGB; break; case DRM_MODE_CONNECTOR_DisplayPort: + case DRM_MODE_CONNECTOR_eDP: radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); if (!radeon_dig_connector) goto failed; @@ -1157,10 +1162,16 @@ radeon_add_atom_connector(struct drm_device *dev, goto failed; if (i2c_bus->valid) { /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); + if (connector_type == DRM_MODE_CONNECTOR_eDP) + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); + else + radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); if (!radeon_dig_connector->dp_i2c_bus) goto failed; - radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); + if (connector_type == DRM_MODE_CONNECTOR_eDP) + radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP"); + else + radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); if (!radeon_connector->ddc_bus) goto failed; } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1fb2f029d7e..0ec491ead2f 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -234,7 +234,7 @@ static const char *encoder_names[34] = { "INTERNAL_UNIPHY2", }; -static const char *connector_names[13] = { +static const char *connector_names[15] = { "Unknown", "VGA", "DVI-I", @@ -248,6 +248,8 @@ static const char *connector_names[13] = { "DisplayPort", "HDMI-A", "HDMI-B", + "TV", + "eDP", }; static const char *hpd_names[7] = { @@ -352,7 +354,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) { int ret = 0; - if (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) { + if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; if (dig->dp_i2c_bus) radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 844c513f724..82eb551970b 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -596,8 +596,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) return ATOM_ENCODER_MODE_LVDS; break; case DRM_MODE_CONNECTOR_DisplayPort: + case DRM_MODE_CONNECTOR_eDP: radeon_dig_connector = radeon_connector->con_priv; - if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) + if ((radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || + (radeon_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; -- cgit v1.2.3 From fc9a89f97e532152ae614d5ce717b81c8f8b0e91 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Thu, 7 Jan 2010 01:35:21 -0500 Subject: drm/radeon: fix a couple of array index errors There are a couple of array overruns, and some associated confusion in the code. This is just a wild guess at what the code should actually look like. Coverity CID: 13305 13306 agd5f: fix up the original intent of the timing code Signed-off-by: Darren Jenkins Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_legacy_tv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_tv.c b/drivers/gpu/drm/radeon/radeon_legacy_tv.c index 3a12bb0c056..417684daef4 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_tv.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_tv.c @@ -77,7 +77,7 @@ struct radeon_tv_mode_constants { unsigned pix_to_tv; }; -static const uint16_t hor_timing_NTSC[] = { +static const uint16_t hor_timing_NTSC[MAX_H_CODE_TIMING_LEN] = { 0x0007, 0x003f, 0x0263, @@ -98,7 +98,7 @@ static const uint16_t hor_timing_NTSC[] = { 0 }; -static const uint16_t vert_timing_NTSC[] = { +static const uint16_t vert_timing_NTSC[MAX_V_CODE_TIMING_LEN] = { 0x2001, 0x200d, 0x1006, @@ -115,7 +115,7 @@ static const uint16_t vert_timing_NTSC[] = { 0 }; -static const uint16_t hor_timing_PAL[] = { +static const uint16_t hor_timing_PAL[MAX_H_CODE_TIMING_LEN] = { 0x0007, 0x0058, 0x027c, @@ -136,7 +136,7 @@ static const uint16_t hor_timing_PAL[] = { 0 }; -static const uint16_t vert_timing_PAL[] = { +static const uint16_t vert_timing_PAL[MAX_V_CODE_TIMING_LEN] = { 0x2001, 0x200c, 0x1005, @@ -623,9 +623,9 @@ void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, } flicker_removal = (tmp + 500) / 1000; - if (flicker_removal < 3) - flicker_removal = 3; - for (i = 0; i < 6; ++i) { + if (flicker_removal < 2) + flicker_removal = 2; + for (i = 0; i < ARRAY_SIZE(SLOPE_limit); ++i) { if (flicker_removal == SLOPE_limit[i]) break; } -- cgit v1.2.3 From 06b6476d6b291473d0928ed242158a001d50c0f0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 5 Jan 2010 11:27:29 -0500 Subject: drm/radeon/kms: detect sideport memory on IGP chips This detects if the sideport memory is enabled and if it is VRAM is evicted on suspend/resume. This should fix s/r issues on some IGPs. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 4 ++++ drivers/gpu/drm/radeon/radeon.h | 4 +++- drivers/gpu/drm/radeon/radeon_atombios.c | 37 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_combios.c | 14 ++++++++++++ drivers/gpu/drm/radeon/radeon_object.c | 5 +++-- drivers/gpu/drm/radeon/rs400.c | 1 + drivers/gpu/drm/radeon/rs600.c | 1 + drivers/gpu/drm/radeon/rs690.c | 1 + 8 files changed, 64 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 5c6058c6ddd..921926f3d1f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -726,6 +726,10 @@ int r600_mc_init(struct radeon_device *rdev) a.full = rfixed_const(100); rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk); rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a); + + if (rdev->flags & RADEON_IS_IGP) + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + return 0; } diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 53b55608102..a7e349dc4b9 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -319,10 +319,12 @@ struct radeon_mc { u64 real_vram_size; int vram_mtrr; bool vram_is_ddr; + bool igp_sideport_enabled; }; int radeon_mc_setup(struct radeon_device *rdev); - +bool radeon_combios_sideport_present(struct radeon_device *rdev); +bool radeon_atombios_sideport_present(struct radeon_device *rdev); /* * GPU scratch registers structures, functions & helpers diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 18340354011..fa82ca74324 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -938,6 +938,43 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) return false; } +union igp_info { + struct _ATOM_INTEGRATED_SYSTEM_INFO info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; +}; + +bool radeon_atombios_sideport_present(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + union igp_info *igp_info; + u8 frev, crev; + u16 data_offset; + + atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, + &crev, &data_offset); + + igp_info = (union igp_info *)(mode_info->atom_context->bios + + data_offset); + + if (igp_info) { + switch (crev) { + case 1: + if (igp_info->info.ucMemoryType & 0xf0) + return true; + break; + case 2: + if (igp_info->info_2.ucMemoryType & 0x0f) + return true; + break; + default: + DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); + break; + } + } + return false; +} + bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder, struct radeon_encoder_int_tmds *tmds) { diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 58f342659cc..7914455c96c 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -595,6 +595,20 @@ bool radeon_combios_get_clock_info(struct drm_device *dev) return false; } +bool radeon_combios_sideport_present(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + u16 igp_info; + + igp_info = combios_get_table_offset(dev, COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE); + + if (igp_info) { + if (RBIOS16(igp_info + 0x4)) + return true; + } + return false; +} + static const uint32_t default_primarydac_adj[CHIP_LAST] = { 0x00000808, /* r100 */ 0x00000808, /* rv100 */ diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index d9ffe1f56e8..4e636de877b 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -221,8 +221,9 @@ int radeon_bo_unpin(struct radeon_bo *bo) int radeon_bo_evict_vram(struct radeon_device *rdev) { if (rdev->flags & RADEON_IS_IGP) { - /* Useless to evict on IGP chips */ - return 0; + if (rdev->mc.igp_sideport_enabled == false) + /* Useless to evict on IGP chips */ + return 0; } return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM); } diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 368415df5f3..bf7b3cf80ed 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -356,6 +356,7 @@ static int rs400_mc_init(struct radeon_device *rdev) rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16; rdev->mc.gtt_location = 0xFFFFFFFFUL; r = radeon_mc_setup(rdev); + rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev); if (r) return r; return 0; diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 4245218e954..19258943a37 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -56,6 +56,7 @@ int rs600_mc_init(struct radeon_device *rdev) rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16; rdev->mc.gtt_location = 0xffffffffUL; r = radeon_mc_setup(rdev); + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); if (r) return r; return 0; diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 1e22f52d603..42f27205a59 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -172,6 +172,7 @@ static int rs690_mc_init(struct radeon_device *rdev) rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16; rdev->mc.gtt_location = 0xFFFFFFFFUL; r = radeon_mc_setup(rdev); + rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); if (r) return r; return 0; -- cgit v1.2.3 From 62cdc0c20663ef840a94850892517b2b7f584904 Mon Sep 17 00:00:00 2001 From: Corbin Simpson Date: Wed, 6 Jan 2010 19:28:48 +0100 Subject: drm/radeon/kms: Workaround RV410/R420 CP errata (V3) Long story short, this fixes sporadic hardlocks with my rv410 during times of intense 2D acceleration (Flash on Fx3). V2: Fix indentation and move errata_fini to suspend function so we don't leak scratch register over suspend/resume cycle. V3: Move scratch_reg to asic specific structure (aim is to slowly move stuff to asic specific structure and avoid poluting radeon_device struct with asic specific variables) Signed-off-by: Corbin Simpson Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r420.c | 31 +++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 1 + 2 files changed, 32 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index c05a7270cf0..f46502a253e 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -30,6 +30,7 @@ #include "radeon_reg.h" #include "radeon.h" #include "atom.h" +#include "r100d.h" #include "r420d.h" int r420_mc_init(struct radeon_device *rdev) @@ -165,6 +166,34 @@ static void r420_clock_resume(struct radeon_device *rdev) WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl); } +static void r420_cp_errata_init(struct radeon_device *rdev) +{ + /* RV410 and R420 can lock up if CP DMA to host memory happens + * while the 2D engine is busy. + * + * The proper workaround is to queue a RESYNC at the beginning + * of the CP init, apparently. + */ + radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch); + radeon_ring_lock(rdev, 8); + radeon_ring_write(rdev, PACKET0(R300_CP_RESYNC_ADDR, 1)); + radeon_ring_write(rdev, rdev->config.r300.resync_scratch); + radeon_ring_write(rdev, 0xDEADBEEF); + radeon_ring_unlock_commit(rdev); +} + +static void r420_cp_errata_fini(struct radeon_device *rdev) +{ + /* Catch the RESYNC we dispatched all the way back, + * at the very beginning of the CP init. + */ + radeon_ring_lock(rdev, 8); + radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + radeon_ring_write(rdev, R300_RB3D_DC_FINISH); + radeon_ring_unlock_commit(rdev); + radeon_scratch_free(rdev, rdev->config.r300.resync_scratch); +} + static int r420_startup(struct radeon_device *rdev) { int r; @@ -196,6 +225,7 @@ static int r420_startup(struct radeon_device *rdev) dev_err(rdev->dev, "failled initializing CP (%d).\n", r); return r; } + r420_cp_errata_init(rdev); r = r100_wb_init(rdev); if (r) { dev_err(rdev->dev, "failled initializing WB (%d).\n", r); @@ -238,6 +268,7 @@ int r420_resume(struct radeon_device *rdev) int r420_suspend(struct radeon_device *rdev) { + r420_cp_errata_fini(rdev); r100_cp_disable(rdev); r100_wb_disable(rdev); r100_irq_disable(rdev); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a7e349dc4b9..cee8bdc6c9f 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -674,6 +674,7 @@ struct r100_asic { struct r300_asic { const unsigned *reg_safe_bm; unsigned reg_safe_bm_size; + u32 resync_scratch; }; struct r600_asic { -- cgit v1.2.3 From cafe6609d6dc0a6a278f9fdbb59ce4d761a35ddd Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 7 Jan 2010 12:39:21 +0100 Subject: drm/radeon/kms: Schedule host path read cache flush through the ring V2 R300 family will hard lockup if host path read cache flush is done through MMIO to HOST_PATH_CNTL. But scheduling same flush through ring seems harmless. This patch remove the hdp_flush callback and add a flush after each fence emission which means a flush after each IB schedule. Thus we should have same behavior without the hard lockup. Tested on R100,R200,R300,R400,R500,R600,R700 family. V2: Adjust fence counts in r600_blit_prepare_copy() Signed-off-by: Jerome Glisse Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 14 ++++++-------- drivers/gpu/drm/radeon/r300.c | 16 +++++++++++++++- drivers/gpu/drm/radeon/r420.c | 1 + drivers/gpu/drm/radeon/r520.c | 1 + drivers/gpu/drm/radeon/r600.c | 7 ++----- drivers/gpu/drm/radeon/r600_blit_kms.c | 4 ++-- drivers/gpu/drm/radeon/radeon.h | 4 ++-- drivers/gpu/drm/radeon/radeon_asic.h | 12 ------------ drivers/gpu/drm/radeon/radeon_gem.c | 2 -- drivers/gpu/drm/radeon/rs400.c | 1 + drivers/gpu/drm/radeon/rs600.c | 1 + drivers/gpu/drm/radeon/rs690.c | 1 + drivers/gpu/drm/radeon/rv515.c | 1 + 13 files changed, 33 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 71727460968..1a056b774ee 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -356,6 +356,11 @@ void r100_fence_ring_emit(struct radeon_device *rdev, /* Wait until IDLE & CLEAN */ radeon_ring_write(rdev, PACKET0(0x1720, 0)); radeon_ring_write(rdev, (1 << 16) | (1 << 17)); + radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(rdev, rdev->config.r100.hdp_cntl | + RADEON_HDP_READ_BUFFER_INVALIDATE); + radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(rdev, rdev->config.r100.hdp_cntl); /* Emit fence sequence & fire IRQ */ radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); radeon_ring_write(rdev, fence->seq); @@ -1713,14 +1718,6 @@ void r100_gpu_init(struct radeon_device *rdev) r100_hdp_reset(rdev); } -void r100_hdp_flush(struct radeon_device *rdev) -{ - u32 tmp; - tmp = RREG32(RADEON_HOST_PATH_CNTL); - tmp |= RADEON_HDP_READ_BUFFER_INVALIDATE; - WREG32(RADEON_HOST_PATH_CNTL, tmp); -} - void r100_hdp_reset(struct radeon_device *rdev) { uint32_t tmp; @@ -3313,6 +3310,7 @@ static int r100_startup(struct radeon_device *rdev) } /* Enable IRQ */ r100_irq_set(rdev); + rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 3f2cc9e2e8d..b8623b734a2 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -36,7 +36,15 @@ #include "rv350d.h" #include "r300_reg_safe.h" -/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 */ +/* This files gather functions specifics to: r300,r350,rv350,rv370,rv380 + * + * GPU Errata: + * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL + * using MMIO to flush host path read cache, this lead to HARDLOCKUP. + * However, scheduling such write to the ring seems harmless, i suspect + * the CP read collide with the flush somehow, or maybe the MC, hard to + * tell. (Jerome Glisse) + */ /* * rv370,rv380 PCIE GART @@ -178,6 +186,11 @@ void r300_fence_ring_emit(struct radeon_device *rdev, /* Wait until IDLE & CLEAN */ radeon_ring_write(rdev, PACKET0(0x1720, 0)); radeon_ring_write(rdev, (1 << 17) | (1 << 16) | (1 << 9)); + radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(rdev, rdev->config.r300.hdp_cntl | + RADEON_HDP_READ_BUFFER_INVALIDATE); + radeon_ring_write(rdev, PACKET0(RADEON_HOST_PATH_CNTL, 0)); + radeon_ring_write(rdev, rdev->config.r300.hdp_cntl); /* Emit fence sequence & fire IRQ */ radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); radeon_ring_write(rdev, fence->seq); @@ -1258,6 +1271,7 @@ static int r300_startup(struct radeon_device *rdev) } /* Enable IRQ */ r100_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index f46502a253e..1d4d16ed7db 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -219,6 +219,7 @@ static int r420_startup(struct radeon_device *rdev) r420_pipes_init(rdev); /* Enable IRQ */ r100_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 0f3843b6dac..9a189072f2b 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -186,6 +186,7 @@ static int r520_startup(struct radeon_device *rdev) } /* Enable IRQ */ rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 921926f3d1f..e2f43c184aa 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1388,11 +1388,6 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) (void)RREG32(PCIE_PORT_DATA); } -void r600_hdp_flush(struct radeon_device *rdev) -{ - WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); -} - /* * CP & Ring */ @@ -1789,6 +1784,8 @@ void r600_fence_ring_emit(struct radeon_device *rdev, radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); radeon_ring_write(rdev, fence->seq); + radeon_ring_write(rdev, PACKET0(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0)); + radeon_ring_write(rdev, 1); /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0)); radeon_ring_write(rdev, RB_INT_STAT); diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 9aecafb51b6..8787ea89dc6 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c @@ -577,9 +577,9 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) ring_size = num_loops * dwords_per_loop; /* set default + shaders */ ring_size += 40; /* shaders + def state */ - ring_size += 5; /* fence emit for VB IB */ + ring_size += 7; /* fence emit for VB IB */ ring_size += 5; /* done copy */ - ring_size += 5; /* fence emit for done copy */ + ring_size += 7; /* fence emit for done copy */ r = radeon_ring_lock(rdev, ring_size); WARN_ON(r); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index cee8bdc6c9f..eb5f99b9469 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -656,7 +656,6 @@ struct radeon_asic { uint32_t offset, uint32_t obj_size); int (*clear_surface_reg)(struct radeon_device *rdev, int reg); void (*bandwidth_update)(struct radeon_device *rdev); - void (*hdp_flush)(struct radeon_device *rdev); void (*hpd_init)(struct radeon_device *rdev); void (*hpd_fini)(struct radeon_device *rdev); bool (*hpd_sense)(struct radeon_device *rdev, enum radeon_hpd_id hpd); @@ -669,12 +668,14 @@ struct radeon_asic { struct r100_asic { const unsigned *reg_safe_bm; unsigned reg_safe_bm_size; + u32 hdp_cntl; }; struct r300_asic { const unsigned *reg_safe_bm; unsigned reg_safe_bm_size; u32 resync_scratch; + u32 hdp_cntl; }; struct r600_asic { @@ -1010,7 +1011,6 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) #define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s))) #define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r))) #define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev)) -#define radeon_hdp_flush(rdev) (rdev)->asic->hdp_flush((rdev)) #define radeon_hpd_init(rdev) (rdev)->asic->hpd_init((rdev)) #define radeon_hpd_fini(rdev) (rdev)->asic->hpd_fini((rdev)) #define radeon_hpd_sense(rdev, hpd) (rdev)->asic->hpd_sense((rdev), (hpd)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index eb29217bbf1..f2fbd2e4e9d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -77,7 +77,6 @@ int r100_clear_surface_reg(struct radeon_device *rdev, int reg); void r100_bandwidth_update(struct radeon_device *rdev); void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); int r100_ring_test(struct radeon_device *rdev); -void r100_hdp_flush(struct radeon_device *rdev); void r100_hpd_init(struct radeon_device *rdev); void r100_hpd_fini(struct radeon_device *rdev); bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); @@ -114,7 +113,6 @@ static struct radeon_asic r100_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &r100_hpd_init, .hpd_fini = &r100_hpd_fini, .hpd_sense = &r100_hpd_sense, @@ -174,7 +172,6 @@ static struct radeon_asic r300_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &r100_hpd_init, .hpd_fini = &r100_hpd_fini, .hpd_sense = &r100_hpd_sense, @@ -218,7 +215,6 @@ static struct radeon_asic r420_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &r100_hpd_init, .hpd_fini = &r100_hpd_fini, .hpd_sense = &r100_hpd_sense, @@ -267,7 +263,6 @@ static struct radeon_asic rs400_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &r100_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &r100_hpd_init, .hpd_fini = &r100_hpd_fini, .hpd_sense = &r100_hpd_sense, @@ -324,7 +319,6 @@ static struct radeon_asic rs600_asic = { .set_pcie_lanes = NULL, .set_clock_gating = &radeon_atom_set_clock_gating, .bandwidth_update = &rs600_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &rs600_hpd_init, .hpd_fini = &rs600_hpd_fini, .hpd_sense = &rs600_hpd_sense, @@ -372,7 +366,6 @@ static struct radeon_asic rs690_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &rs690_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &rs600_hpd_init, .hpd_fini = &rs600_hpd_fini, .hpd_sense = &rs600_hpd_sense, @@ -424,7 +417,6 @@ static struct radeon_asic rv515_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &rs600_hpd_init, .hpd_fini = &rs600_hpd_fini, .hpd_sense = &rs600_hpd_sense, @@ -467,7 +459,6 @@ static struct radeon_asic r520_asic = { .set_surface_reg = r100_set_surface_reg, .clear_surface_reg = r100_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, - .hdp_flush = &r100_hdp_flush, .hpd_init = &rs600_hpd_init, .hpd_fini = &rs600_hpd_fini, .hpd_sense = &rs600_hpd_sense, @@ -508,7 +499,6 @@ int r600_ring_test(struct radeon_device *rdev); int r600_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_pages, struct radeon_fence *fence); -void r600_hdp_flush(struct radeon_device *rdev); void r600_hpd_init(struct radeon_device *rdev); void r600_hpd_fini(struct radeon_device *rdev); bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); @@ -544,7 +534,6 @@ static struct radeon_asic r600_asic = { .set_surface_reg = r600_set_surface_reg, .clear_surface_reg = r600_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, - .hdp_flush = &r600_hdp_flush, .hpd_init = &r600_hpd_init, .hpd_fini = &r600_hpd_fini, .hpd_sense = &r600_hpd_sense, @@ -589,7 +578,6 @@ static struct radeon_asic rv770_asic = { .set_surface_reg = r600_set_surface_reg, .clear_surface_reg = r600_clear_surface_reg, .bandwidth_update = &rv515_bandwidth_update, - .hdp_flush = &r600_hdp_flush, .hpd_init = &r600_hpd_init, .hpd_fini = &r600_hpd_fini, .hpd_sense = &r600_hpd_sense, diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 60df2d7e7e4..0e1325e1853 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -131,7 +131,6 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj, printk(KERN_ERR "Failed to wait for object !\n"); return r; } - radeon_hdp_flush(robj->rdev); } return 0; } @@ -312,7 +311,6 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, mutex_lock(&dev->struct_mutex); drm_gem_object_unreference(gobj); mutex_unlock(&dev->struct_mutex); - radeon_hdp_flush(robj->rdev); return r; } diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index bf7b3cf80ed..9f5418983e2 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -396,6 +396,7 @@ static int rs400_startup(struct radeon_device *rdev) return r; /* Enable IRQ */ r100_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 19258943a37..a0378c57e4e 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -554,6 +554,7 @@ static int rs600_startup(struct radeon_device *rdev) return r; /* Enable IRQ */ rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 42f27205a59..cd31da91377 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -626,6 +626,7 @@ static int rs690_startup(struct radeon_device *rdev) return r; /* Enable IRQ */ rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 59632a506b4..62756717b04 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -479,6 +479,7 @@ static int rv515_startup(struct radeon_device *rdev) } /* Enable IRQ */ rs600_irq_set(rdev); + rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); if (r) { -- cgit v1.2.3 From d0269ed8580b492df75dafb011dc51a1390bf200 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 7 Jan 2010 16:08:32 +0100 Subject: drm/radeon/kms: Make sure we release AGP device if we acquired it In some case we weren't releasing the AGP device at module unloading. This leaded to unfunctional AGP at next module load. This patch make sure we release the AGP bus if we acquire it. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 1 + drivers/gpu/drm/radeon/r300.c | 1 + drivers/gpu/drm/radeon/r600.c | 3 +-- drivers/gpu/drm/radeon/radeon_agp.c | 6 ++---- drivers/gpu/drm/radeon/rv770.c | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 1a056b774ee..d2b789e67c3 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3369,6 +3369,7 @@ void r100_fini(struct radeon_device *rdev) radeon_gem_fini(rdev); if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); radeon_bo_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index b8623b734a2..0051d11b907 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1336,6 +1336,7 @@ void r300_fini(struct radeon_device *rdev) rv370_pcie_gart_fini(rdev); if (rdev->flags & RADEON_IS_PCI) r100_pci_gart_fini(rdev); + radeon_agp_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); radeon_bo_fini(rdev); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index e2f43c184aa..0c065f425c8 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2090,8 +2090,7 @@ void r600_fini(struct radeon_device *rdev) radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); - if (rdev->flags & RADEON_IS_AGP) - radeon_agp_fini(rdev); + radeon_agp_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 54bf49a6d67..220f454ea9f 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -252,10 +252,8 @@ void radeon_agp_resume(struct radeon_device *rdev) void radeon_agp_fini(struct radeon_device *rdev) { #if __OS_HAS_AGP - if (rdev->flags & RADEON_IS_AGP) { - if (rdev->ddev->agp && rdev->ddev->agp->acquired) { - drm_agp_release(rdev->ddev); - } + if (rdev->ddev->agp && rdev->ddev->agp->acquired) { + drm_agp_release(rdev->ddev); } #endif } diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index f58dc671080..16f7317fa1a 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1096,8 +1096,7 @@ void rv770_fini(struct radeon_device *rdev) radeon_gem_fini(rdev); radeon_fence_driver_fini(rdev); radeon_clocks_fini(rdev); - if (rdev->flags & RADEON_IS_AGP) - radeon_agp_fini(rdev); + radeon_agp_fini(rdev); radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); -- cgit v1.2.3 From 059d233f9c1183ed2f59d631e4daf486060e880d Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 7 Jan 2010 02:59:31 +0300 Subject: drm/radeon: mkregtable.c: close a file before exit Signed-off-by: Alexander Beregalov Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/mkregtable.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/mkregtable.c b/drivers/gpu/drm/radeon/mkregtable.c index 0d79577c157..607241c6a8a 100644 --- a/drivers/gpu/drm/radeon/mkregtable.c +++ b/drivers/gpu/drm/radeon/mkregtable.c @@ -661,8 +661,10 @@ static int parser_auth(struct table *t, const char *filename) fseek(file, 0, SEEK_SET); /* get header */ - if (fgets(buf, 1024, file) == NULL) + if (fgets(buf, 1024, file) == NULL) { + fclose(file); return -1; + } /* first line will contain the last register * and gpu name */ -- cgit v1.2.3 From e77cef9c2d87db835ad9d70cde4a9b00b0ca2262 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 7 Jan 2010 15:39:13 +0100 Subject: drm: Avoid calling vblank function is vblank wasn't initialized In some case vblank might not be initialized and we shouldn't try to use associated function. This patch make sure this is the case. It also export drm_vblank_cleanup so driver can cleanup vblank if for any reason IRQ/MSI is not working. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 7998ee66b31..b98384dbd9a 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -115,6 +115,7 @@ void drm_vblank_cleanup(struct drm_device *dev) dev->num_crtcs = 0; } +EXPORT_SYMBOL(drm_vblank_cleanup); int drm_vblank_init(struct drm_device *dev, int num_crtcs) { @@ -163,7 +164,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) } dev->vblank_disable_allowed = 0; - return 0; err: @@ -493,6 +493,9 @@ EXPORT_SYMBOL(drm_vblank_off); */ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) { + /* vblank is not initialized (IRQ not installed ?) */ + if (!dev->num_crtcs) + return; /* * To avoid all the problems that might happen if interrupts * were enabled/disabled around or between these calls, we just -- cgit v1.2.3 From 003e69f9862bcda89a75c27750efdbc17ac02945 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 7 Jan 2010 15:39:14 +0100 Subject: drm/radeon/kms: Don't try to enable IRQ if we have no handler installed If for any reason we haven't installed handler we shouldn't try to enable IRQ/MSI on the hw so we don't get unhandled IRQ/MSI which makes the kernel sad. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 8 +++++++- drivers/gpu/drm/radeon/r600.c | 7 ++++++- drivers/gpu/drm/radeon/radeon_irq_kms.c | 10 ++++++++-- drivers/gpu/drm/radeon/rs600.c | 8 +++++++- 4 files changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index d2b789e67c3..8760d66e058 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -131,7 +131,8 @@ void r100_hpd_init(struct radeon_device *rdev) break; } } - r100_irq_set(rdev); + if (rdev->irq.installed) + r100_irq_set(rdev); } void r100_hpd_fini(struct radeon_device *rdev) @@ -243,6 +244,11 @@ int r100_irq_set(struct radeon_device *rdev) { uint32_t tmp = 0; + if (!rdev->irq.installed) { + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); + WREG32(R_000040_GEN_INT_CNTL, 0); + return -EINVAL; + } if (rdev->irq.sw_int) { tmp |= RADEON_SW_INT_ENABLE; } diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 0c065f425c8..1f4f83d6fbe 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -285,7 +285,8 @@ void r600_hpd_init(struct radeon_device *rdev) } } } - r600_irq_set(rdev); + if (rdev->irq.installed) + r600_irq_set(rdev); } void r600_hpd_fini(struct radeon_device *rdev) @@ -2461,6 +2462,10 @@ int r600_irq_set(struct radeon_device *rdev) u32 mode_int = 0; u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; + if (!rdev->irq.installed) { + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); + return -EINVAL; + } /* don't enable anything if the ih is disabled */ if (!rdev->ih.enabled) return 0; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 9223296fe37..3cfd60fd008 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -97,6 +97,7 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) rdev->irq.sw_int = false; for (i = 0; i < 2; i++) { rdev->irq.crtc_vblank_int[i] = false; + rdev->irq.hpd[i] = false; } radeon_irq_set(rdev); } @@ -128,17 +129,22 @@ int radeon_irq_kms_init(struct radeon_device *rdev) DRM_INFO("radeon: using MSI.\n"); } } - drm_irq_install(rdev->ddev); rdev->irq.installed = true; + r = drm_irq_install(rdev->ddev); + if (r) { + rdev->irq.installed = false; + return r; + } DRM_INFO("radeon: irq initialized.\n"); return 0; } void radeon_irq_kms_fini(struct radeon_device *rdev) { + drm_vblank_cleanup(rdev->ddev); if (rdev->irq.installed) { - rdev->irq.installed = false; drm_irq_uninstall(rdev->ddev); + rdev->irq.installed = false; if (rdev->msi_enabled) pci_disable_msi(rdev->pdev); } diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index a0378c57e4e..d5255751e7b 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -135,7 +135,8 @@ void rs600_hpd_init(struct radeon_device *rdev) break; } } - rs600_irq_set(rdev); + if (rdev->irq.installed) + rs600_irq_set(rdev); } void rs600_hpd_fini(struct radeon_device *rdev) @@ -316,6 +317,11 @@ int rs600_irq_set(struct radeon_device *rdev) u32 hpd2 = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~S_007D18_DC_HOT_PLUG_DETECT2_INT_EN(1); + if (!rdev->irq.installed) { + WARN(1, "Can't enable IRQ/MSI because no handler is installed.\n"); + WREG32(R_000040_GEN_INT_CNTL, 0); + return -EINVAL; + } if (rdev->irq.sw_int) { tmp |= S_000040_SW_INT_EN(1); } -- cgit v1.2.3 From 397bb3c2e0810d56518e5e111fcedb593823514f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Dec 2009 13:37:31 +0200 Subject: OMAP: DSS2: DSI: fix VC channels in send_short and send_null - dsi_vc_send_short() needs to use dest_per for the peripheral id - dsi_vc_send_null() was always using channel id 0 Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 5936487b5de..341c6bb2650 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -1999,7 +1999,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) return -EINVAL; } - data_id = data_type | channel << 6; + data_id = data_type | dsi.vc[channel].dest_per << 6; r = (data_id << 0) | (data << 8) | (ecc << 24); @@ -2011,7 +2011,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) int dsi_vc_send_null(int channel) { u8 nullpkg[] = {0, 0, 0, 0}; - return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0); + return dsi_vc_send_long(channel, DSI_DT_NULL_PACKET, nullpkg, 4, 0); } EXPORT_SYMBOL(dsi_vc_send_null); -- cgit v1.2.3 From ff90a3488d98a63bf24bff37f77a9a37b00e7a54 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Dec 2009 13:38:04 +0200 Subject: OMAP: DSS2: DSI: print debug DCS cmd in hex Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 341c6bb2650..e65056317a2 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2058,7 +2058,7 @@ int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) int r; if (dsi.debug_read) - DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd); + DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); if (r) -- cgit v1.2.3 From dfc0fd8d8850ef11951ba6c251e06096d1b5a0bd Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 17 Dec 2009 14:35:21 +0200 Subject: OMAP: DSS2: Collect interrupt statistics Collect interrupt statistics, printable via debugfs: debugfs/omapdss/dispc_irq debugfs/omapdss/dsi_irq The counters are reset when printed. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 7 +++ drivers/video/omap2/dss/core.c | 8 +++ drivers/video/omap2/dss/dispc.c | 67 +++++++++++++++++++++ drivers/video/omap2/dss/dsi.c | 125 ++++++++++++++++++++++++++++++++++++++++ drivers/video/omap2/dss/dss.h | 14 +++++ 5 files changed, 221 insertions(+) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 71d8dec3063..c63ce767b27 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -25,6 +25,13 @@ config OMAP2_DSS_DEBUG_SUPPORT This enables debug messages. You need to enable printing with 'debug' module parameter. +config OMAP2_DSS_COLLECT_IRQ_STATS + bool "Collect DSS IRQ statistics" + depends on OMAP2_DSS_DEBUG_SUPPORT + default n + help + Collect DSS IRQ statistics, printable via debugfs + config OMAP2_DSS_RFBI bool "RFBI support" default n diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 29497a0c9a9..dbb0ce243f0 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -395,6 +395,14 @@ static int dss_initialize_debugfs(void) debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, &dss_debug_dump_clocks, &dss_debug_fops); + debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir, + &dispc_dump_irqs, &dss_debug_fops); + +#ifdef CONFIG_OMAP2_DSS_DSI + debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir, + &dsi_dump_irqs, &dss_debug_fops); +#endif + debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, &dss_dump_regs, &dss_debug_fops); debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 6dabf4b2f00..e2e0f9ae735 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -148,6 +148,12 @@ static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, DISPC_VID_ATTRIBUTES(0), DISPC_VID_ATTRIBUTES(1) }; +struct dispc_irq_stats { + unsigned long last_reset; + unsigned irq_count; + unsigned irqs[32]; +}; + static struct { void __iomem *base; @@ -160,6 +166,11 @@ static struct { struct work_struct error_work; u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spinlock_t irq_stats_lock; + struct dispc_irq_stats irq_stats; +#endif } dispc; static void _omap_dispc_set_irqs(void); @@ -2247,6 +2258,50 @@ void dispc_dump_clocks(struct seq_file *s) enable_clocks(0); } +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +void dispc_dump_irqs(struct seq_file *s) +{ + unsigned long flags; + struct dispc_irq_stats stats; + + spin_lock_irqsave(&dispc.irq_stats_lock, flags); + + stats = dispc.irq_stats; + memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats)); + dispc.irq_stats.last_reset = jiffies; + + spin_unlock_irqrestore(&dispc.irq_stats_lock, flags); + + seq_printf(s, "period %u ms\n", + jiffies_to_msecs(jiffies - stats.last_reset)); + + seq_printf(s, "irqs %d\n", stats.irq_count); +#define PIS(x) \ + seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]); + + PIS(FRAMEDONE); + PIS(VSYNC); + PIS(EVSYNC_EVEN); + PIS(EVSYNC_ODD); + PIS(ACBIAS_COUNT_STAT); + PIS(PROG_LINE_NUM); + PIS(GFX_FIFO_UNDERFLOW); + PIS(GFX_END_WIN); + PIS(PAL_GAMMA_MASK); + PIS(OCP_ERR); + PIS(VID1_FIFO_UNDERFLOW); + PIS(VID1_END_WIN); + PIS(VID2_FIFO_UNDERFLOW); + PIS(VID2_END_WIN); + PIS(SYNC_LOST); + PIS(SYNC_LOST_DIGIT); + PIS(WAKEUP); +#undef PIS +} +#else +void dispc_dump_irqs(struct seq_file *s) { } +#endif + void dispc_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) @@ -2665,6 +2720,13 @@ void dispc_irq_handler(void) irqstatus = dispc_read_reg(DISPC_IRQSTATUS); +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock(&dispc.irq_stats_lock); + dispc.irq_stats.irq_count++; + dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs); + spin_unlock(&dispc.irq_stats_lock); +#endif + #ifdef DEBUG if (dss_debug) print_irq_status(irqstatus); @@ -3012,6 +3074,11 @@ int dispc_init(void) spin_lock_init(&dispc.irq_lock); +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock_init(&dispc.irq_stats_lock); + dispc.irq_stats.last_reset = jiffies; +#endif + INIT_WORK(&dispc.error_work, dispc_error_worker); dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index e65056317a2..03f85df7074 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -204,6 +204,14 @@ struct dsi_update_region { struct omap_dss_device *device; }; +struct dsi_irq_stats { + unsigned long last_reset; + unsigned irq_count; + unsigned dsi_irqs[32]; + unsigned vc_irqs[4][32]; + unsigned cio_irqs[32]; +}; + static struct { void __iomem *base; @@ -258,6 +266,11 @@ static struct #endif int debug_read; int debug_write; + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spinlock_t irq_stats_lock; + struct dsi_irq_stats irq_stats; +#endif } dsi; #ifdef DEBUG @@ -528,6 +541,12 @@ void dsi_irq_handler(void) irqstatus = dsi_read_reg(DSI_IRQSTATUS); +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock(&dsi.irq_stats_lock); + dsi.irq_stats.irq_count++; + dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); +#endif + if (irqstatus & DSI_IRQ_ERROR_MASK) { DSSERR("DSI error, irqstatus %x\n", irqstatus); print_irq_status(irqstatus); @@ -549,6 +568,10 @@ void dsi_irq_handler(void) vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); +#endif + if (vcstatus & DSI_VC_IRQ_BTA) complete(&dsi.bta_completion); @@ -568,6 +591,10 @@ void dsi_irq_handler(void) if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); +#endif + dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); /* flush posted write */ dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); @@ -579,6 +606,10 @@ void dsi_irq_handler(void) dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); /* flush posted write */ dsi_read_reg(DSI_IRQSTATUS); + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_unlock(&dsi.irq_stats_lock); +#endif } @@ -1226,6 +1257,95 @@ void dsi_dump_clocks(struct seq_file *s) enable_clocks(0); } +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +void dsi_dump_irqs(struct seq_file *s) +{ + unsigned long flags; + struct dsi_irq_stats stats; + + spin_lock_irqsave(&dsi.irq_stats_lock, flags); + + stats = dsi.irq_stats; + memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats)); + dsi.irq_stats.last_reset = jiffies; + + spin_unlock_irqrestore(&dsi.irq_stats_lock, flags); + + seq_printf(s, "period %u ms\n", + jiffies_to_msecs(jiffies - stats.last_reset)); + + seq_printf(s, "irqs %d\n", stats.irq_count); +#define PIS(x) \ + seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); + + seq_printf(s, "-- DSI interrupts --\n"); + PIS(VC0); + PIS(VC1); + PIS(VC2); + PIS(VC3); + PIS(WAKEUP); + PIS(RESYNC); + PIS(PLL_LOCK); + PIS(PLL_UNLOCK); + PIS(PLL_RECALL); + PIS(COMPLEXIO_ERR); + PIS(HS_TX_TIMEOUT); + PIS(LP_RX_TIMEOUT); + PIS(TE_TRIGGER); + PIS(ACK_TRIGGER); + PIS(SYNC_LOST); + PIS(LDO_POWER_GOOD); + PIS(TA_TIMEOUT); +#undef PIS + +#define PIS(x) \ + seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \ + stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \ + stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \ + stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \ + stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]); + + seq_printf(s, "-- VC interrupts --\n"); + PIS(CS); + PIS(ECC_CORR); + PIS(PACKET_SENT); + PIS(FIFO_TX_OVF); + PIS(FIFO_RX_OVF); + PIS(BTA); + PIS(ECC_NO_CORR); + PIS(FIFO_TX_UDF); + PIS(PP_BUSY_CHANGE); +#undef PIS + +#define PIS(x) \ + seq_printf(s, "%-20s %10d\n", #x, \ + stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]); + + seq_printf(s, "-- CIO interrupts --\n"); + PIS(ERRSYNCESC1); + PIS(ERRSYNCESC2); + PIS(ERRSYNCESC3); + PIS(ERRESC1); + PIS(ERRESC2); + PIS(ERRESC3); + PIS(ERRCONTROL1); + PIS(ERRCONTROL2); + PIS(ERRCONTROL3); + PIS(STATEULPS1); + PIS(STATEULPS2); + PIS(STATEULPS3); + PIS(ERRCONTENTIONLP0_1); + PIS(ERRCONTENTIONLP1_1); + PIS(ERRCONTENTIONLP0_2); + PIS(ERRCONTENTIONLP1_2); + PIS(ERRCONTENTIONLP0_3); + PIS(ERRCONTENTIONLP1_3); + PIS(ULPSACTIVENOT_ALL0); + PIS(ULPSACTIVENOT_ALL1); +#undef PIS +} +#endif + void dsi_dump_regs(struct seq_file *s) { #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) @@ -3637,6 +3757,11 @@ int dsi_init(struct platform_device *pdev) spin_lock_init(&dsi.errors_lock); dsi.errors = 0; +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS + spin_lock_init(&dsi.irq_stats_lock); + dsi.irq_stats.last_reset = jiffies; +#endif + init_completion(&dsi.bta_completion); init_completion(&dsi.update_completion); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 8da5ac42151..2bcb1245d6c 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -240,6 +240,7 @@ int dsi_init(struct platform_device *pdev); void dsi_exit(void); void dsi_dump_clocks(struct seq_file *s); +void dsi_dump_irqs(struct seq_file *s); void dsi_dump_regs(struct seq_file *s); void dsi_save_context(void); @@ -268,6 +269,7 @@ int dpi_init_display(struct omap_dss_device *dssdev); int dispc_init(void); void dispc_exit(void); void dispc_dump_clocks(struct seq_file *s); +void dispc_dump_irqs(struct seq_file *s); void dispc_dump_regs(struct seq_file *s); void dispc_irq_handler(void); void dispc_fake_vsync_irq(void); @@ -367,4 +369,16 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); unsigned long rfbi_get_max_tx_rate(void); int rfbi_init_display(struct omap_dss_device *display); + +#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS +static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr) +{ + int b; + for (b = 0; b < 32; ++b) { + if (irqstatus & (1 << b)) + irq_arr[b]++; + } +} +#endif + #endif -- cgit v1.2.3 From 7475e44246e8a7c435a7ed8fe1e94fc8898685d9 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Dec 2009 17:30:24 +0200 Subject: OMAP: DSS2: Fix crash when panel doesn't define enable_te() DSI driver didn't check if the panel driver actually implements enable_te(). Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 03f85df7074..e32a53c0889 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -2932,11 +2932,15 @@ static int dsi_set_update_mode(struct omap_dss_device *dssdev, static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) { - int r; - r = dssdev->driver->enable_te(dssdev, enable); - /* XXX for some reason, DSI TE breaks if we don't wait here. - * Panel bug? Needs more studying */ - msleep(100); + int r = 0; + + if (dssdev->driver->enable_te) { + r = dssdev->driver->enable_te(dssdev, enable); + /* XXX for some reason, DSI TE breaks if we don't wait here. + * Panel bug? Needs more studying */ + msleep(100); + } + return r; } -- cgit v1.2.3 From 66215949e6512f61c2c92b65ea79f8566e9e650a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 8 Jan 2010 10:29:06 -0800 Subject: omap1: Fix compile for omap1_bl.c Commit 9905a43b made struct backlight_ops const. Omap was setting check_fb dynamically, which caused the following compile error: drivers/video/backlight/omap1_bl.c: In function 'omapbl_probe': drivers/video/backlight/omap1_bl.c:142: error: assignment of read-only variable 'omapbl_ops' Turns out pdata->check_fb is not being used, so just remove it to fix the compile. Cc: Emese Revfy Cc: Richard Purdie Signed-off-by: Tony Lindgren --- drivers/video/backlight/omap1_bl.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 409ca964352..a3a7f893817 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -139,8 +139,6 @@ static int omapbl_probe(struct platform_device *pdev) if (!pdata) return -ENXIO; - omapbl_ops.check_fb = pdata->check_fb; - bl = kzalloc(sizeof(struct omap_backlight), GFP_KERNEL); if (unlikely(!bl)) return -ENOMEM; -- cgit v1.2.3 From c8106d7625a58ee4387cb2efe3e82320ad44b467 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 8 Jan 2010 10:04:30 -0800 Subject: iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr When txq read_ptr equals to write_ptr, iwl_queue_used should always return false. Because there is no used TFD in this case. This is a complementary fix to the fix already included in commit "iwl3945: fix panic in iwl3945 driver". Both fixes are needed to address the panic below. This problem was discussed on linux-wireless in http://thread.gmane.org/gmane.linux.kernel.wireless.general/43568 <1>[ 7290.414172] IP: [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.414205] PGD 0 <1>[ 7290.414214] Thread overran stack, or stack corrupted <0>[ 7290.414229] Oops: 0002 [#1] PREEMPT SMP <0>[ 7290.414246] last sysfs file: /sys/devices/platform/coretemp.1/temp1_input <4>[ 7290.414265] CPU 0 <4>[ 7290.414274] Modules linked in: af_packet nfsd usb_storage usb_libusual cpufreq_powersave exportfs cpufreq_conservative iwl3945 nfs cpufreq_userspace snd_hda_codec_realtek acpi_cpufreq uvcvideo lockd iwlcore snd_hda_intel joydev coretemp nfs_acl videodev snd_hda_codec mac80211 v4l1_compat snd_hwdep sbp2 v4l2_compat_ioctl32 uhci_hcd psmouse auth_rpcgss ohci1394 cfg80211 ehci_hcd video ieee1394 snd_pcm serio_raw battery ac nvidia(P) usbcore output sunrpc evdev lirc_ene0100 snd_page_alloc rfkill tg3 libphy fuse lzo lzo_decompress lzo_compress <6>[ 7290.414486] Pid: 0, comm: swapper Tainted: P 2.6.32-rc8-wl #213 Aspire 5720 <6>[ 7290.414507] RIP: 0010:[] [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <6>[ 7290.414541] RSP: 0018:ffff880002203d60 EFLAGS: 00010246 <6>[ 7290.414557] RAX: 000000000000004f RBX: ffff880064c11600 RCX: 0000000000000013 <6>[ 7290.414576] RDX: ffffffffa0ddcf20 RSI: ffff8800512b7008 RDI: 0000000000000038 <6>[ 7290.414596] RBP: ffff880002203dd0 R08: 0000000000000000 R09: 0000000000000100 <6>[ 7290.414616] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000000000a0 <6>[ 7290.414635] R13: 0000000000000002 R14: 0000000000000013 R15: 0000000000020201 <6>[ 7290.414655] FS: 0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000 <6>[ 7290.414677] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b <6>[ 7290.414693] CR2: 0000000000000041 CR3: 0000000001001000 CR4: 00000000000006f0 <6>[ 7290.414712] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 <6>[ 7290.414732] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 <4>[ 7290.414752] Process swapper (pid: 0, threadinfo ffffffff81524000, task ffffffff81528b60) <0>[ 7290.414772] Stack: <4>[ 7290.414780] ffff880002203da0 0000000000000046 0000000000000000 0000000000000046 <4>[ 7290.414804] <0> 0000000000000282 0000000000000282 0000000000000282 ffff880064c12010 <4>[ 7290.414830] <0> ffff880002203db0 ffff880064c11600 ffff880064c12e50 ffff8800512b7000 <0>[ 7290.414858] Call Trace: <0>[ 7290.414867] <4>[ 7290.414884] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.414910] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.414931] [] tasklet_action+0x101/0x110 <4>[ 7290.414950] [] __do_softirq+0xc0/0x160 <4>[ 7290.414968] [] call_softirq+0x1c/0x30 <4>[ 7290.414986] [] do_softirq+0x75/0xb0 <4>[ 7290.415003] [] irq_exit+0x95/0xa0 <4>[ 7290.415020] [] do_IRQ+0x77/0xf0 <4>[ 7290.415038] [] ret_from_intr+0x0/0xf <0>[ 7290.415052] <4>[ 7290.415067] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415087] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415107] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415130] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415149] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415168] [] ? rest_init+0x75/0x80 <4>[ 7290.415187] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.415206] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.415227] [] ? x86_64_start_kernel+0xe4/0xeb <0>[ 7290.415243] Code: 00 41 39 ce 0f 8d e8 01 00 00 48 8b 47 40 48 63 d2 48 69 d2 98 00 00 00 4c 8b 04 02 48 c7 c2 20 cf dd a0 49 8d 78 38 49 8d 40 4f 47 09 00 c6 47 0c 00 c6 47 0f 00 c6 47 12 00 c6 47 15 00 49 <1>[ 7290.415382] RIP [] iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415410] RSP <0>[ 7290.415421] CR2: 0000000000000041 <4>[ 7290.415436] ---[ end trace ec46807277caa515 ]--- <0>[ 7290.415450] Kernel panic - not syncing: Fatal exception in interrupt <4>[ 7290.415468] Pid: 0, comm: swapper Tainted: P D 2.6.32-rc8-wl #213 <4>[ 7290.415486] Call Trace: <4>[ 7290.415495] [] panic+0x7d/0x13a <4>[ 7290.415519] [] oops_end+0xda/0xe0 <4>[ 7290.415538] [] no_context+0xea/0x250 <4>[ 7290.415557] [] ? select_task_rq_fair+0x511/0x780 <4>[ 7290.415578] [] __bad_area_nosemaphore+0x125/0x1e0 <4>[ 7290.415597] [] ? __enqueue_entity+0x7c/0x80 <4>[ 7290.415616] [] ? enqueue_task_fair+0x111/0x150 <4>[ 7290.415636] [] bad_area_nosemaphore+0xe/0x10 <4>[ 7290.415656] [] do_page_fault+0x26a/0x320 <4>[ 7290.415674] [] page_fault+0x1f/0x30 <4>[ 7290.415697] [] ? iwl3945_rx_reply_tx+0xc1/0x450 [iwl3945] <4>[ 7290.415723] [] iwl3945_irq_tasklet+0x657/0x1740 [iwl3945] <4>[ 7290.415746] [] ? _spin_unlock+0x30/0x60 <4>[ 7290.415764] [] tasklet_action+0x101/0x110 <4>[ 7290.415783] [] __do_softirq+0xc0/0x160 <4>[ 7290.415801] [] call_softirq+0x1c/0x30 <4>[ 7290.415818] [] do_softirq+0x75/0xb0 <4>[ 7290.415835] [] irq_exit+0x95/0xa0 <4>[ 7290.415852] [] do_IRQ+0x77/0xf0 <4>[ 7290.415869] [] ret_from_intr+0x0/0xf <4>[ 7290.415883] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415911] [] ? acpi_idle_enter_bm+0x27a/0x2a5 <4>[ 7290.415931] [] ? acpi_idle_enter_bm+0x270/0x2a5 <4>[ 7290.415952] [] ? cpuidle_idle_call+0x93/0xf0 <4>[ 7290.415971] [] ? cpu_idle+0xa7/0x110 <4>[ 7290.415989] [] ? rest_init+0x75/0x80 <4>[ 7290.416007] [] ? start_kernel+0x3a7/0x3b3 <4>[ 7290.416026] [] ? x86_64_start_reservations+0x125/0x129 <4>[ 7290.416047] [] ? x86_64_start_kernel+0xe4/0xeb Reported-by: Maxim Levitsky Tested-by: Maxim Levitsky Signed-off-by: Zhu Yi Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 165d1f6e2dd..3822cf53e36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -711,7 +711,7 @@ extern void iwl_txq_ctx_stop(struct iwl_priv *priv); extern int iwl_queue_space(const struct iwl_queue *q); static inline int iwl_queue_used(const struct iwl_queue *q, int i) { - return q->write_ptr > q->read_ptr ? + return q->write_ptr >= q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } -- cgit v1.2.3 From c91c3efca5297bd67324654524ced38162f2e579 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 8 Jan 2010 10:04:31 -0800 Subject: iwlwifi: disable tx on beacon update notification On beacon change update notification from mac we are not disabling the tx in adhoc mode. Mac sends BSS_CHANGED_BEACON_ENABLED when station leaves IBSS. Driver should indicate uCode to not to send anything on receiving this notification. Functionality to indicate uCode is duplicated across two notifications so created a common function called iwl_set_no_assoc. Fix the issue at http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2133. Signed-off-by: Abhijeet Kolekar Tested-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 45 ++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 574d3665870..5461f105bd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2344,6 +2344,21 @@ static void iwl_ht_conf(struct iwl_priv *priv, IWL_DEBUG_MAC80211(priv, "leave\n"); } +static inline void iwl_set_no_assoc(struct iwl_priv *priv) +{ + priv->assoc_id = 0; + iwl_led_disassociate(priv); + /* + * inform the ucode that there is no longer an + * association and that no more packets should be + * sent + */ + priv->staging_rxon.filter_flags &= + ~RXON_FILTER_ASSOC_MSK; + priv->staging_rxon.assoc_id = 0; + iwlcore_commit_rxon(priv); +} + #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2475,20 +2490,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; if (!iwl_is_rfkill(priv)) priv->cfg->ops->lib->post_associate(priv); - } else { - priv->assoc_id = 0; - iwl_led_disassociate(priv); - - /* - * inform the ucode that there is no longer an - * association and that no more packets should be - * send - */ - priv->staging_rxon.filter_flags &= - ~RXON_FILTER_ASSOC_MSK; - priv->staging_rxon.assoc_id = 0; - iwlcore_commit_rxon(priv); - } + } else + iwl_set_no_assoc(priv); } if (changes && iwl_is_associated(priv) && priv->assoc_id) { @@ -2503,12 +2506,14 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } } - if ((changes & BSS_CHANGED_BEACON_ENABLED) && - vif->bss_conf.enable_beacon) { - memcpy(priv->staging_rxon.bssid_addr, - bss_conf->bssid, ETH_ALEN); - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - iwlcore_config_ap(priv); + if (changes & BSS_CHANGED_BEACON_ENABLED) { + if (vif->bss_conf.enable_beacon) { + memcpy(priv->staging_rxon.bssid_addr, + bss_conf->bssid, ETH_ALEN); + memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + iwlcore_config_ap(priv); + } else + iwl_set_no_assoc(priv); } mutex_unlock(&priv->mutex); -- cgit v1.2.3 From 50f411e34d623efbf4e4b4b0c1a4a20e04c5cc9e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Jan 2010 00:45:33 +0100 Subject: DRM / i915: Fix resume regression on MSI Wind U100 w/o KMS Commit cbda12d77ea590082edb6d30bd342a67ebc459e0 (drm/i915: implement new pm ops for i915), among other things, removed the .suspend and .resume pointers from the struct drm_driver object in i915_drv.c, which broke resume without KMS on my MSI Wind U100. Fix this by reverting that part of commit cbda12d77ea59. [ The DRM layer will not use the class-specific suspend/resume functions if the driver is marked MODESET-aware, and conversely it will not register the PCI device if the drievr isn't so marked, so you always end up with _either_ the drm-class suspend/resume _or_ the PCI layer PM functionality, never both. - Linus ] Signed-off-by: Rafael J. Wysocki Acked-by: Jesse Barnes Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2ffffd7ae09..be631cc3e4d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -464,6 +464,8 @@ static struct drm_driver driver = { .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .postclose = i915_driver_postclose, + .suspend = i915_suspend, + .resume = i915_resume, .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, -- cgit v1.2.3 From dd38d6889dc5dae2014d9eac72fae32f477f294e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 9 Jan 2010 00:13:36 -0800 Subject: Input: xbox - do not use GFP_KERNEL under spinlock xbox_play_effect() is called while holding dev->event_lock with interrupts disabled and thus may not use GFP_KERNEL when submitting urbs. Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/xpad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 482cb1204e4..8a28fb7846d 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -446,7 +446,7 @@ static void xpad_irq_in(struct urb *urb) } exit: - retval = usb_submit_urb (urb, GFP_ATOMIC); + retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err ("%s - usb_submit_urb failed with result %d", __func__, retval); @@ -571,7 +571,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, xpad->odata[6] = 0x00; xpad->odata[7] = 0x00; xpad->irq_out->transfer_buffer_length = 8; - usb_submit_urb(xpad->irq_out, GFP_KERNEL); + usb_submit_urb(xpad->irq_out, GFP_ATOMIC); } return 0; -- cgit v1.2.3 From bb595c923bc51dff9cdd112de18deb57ac7945d2 Mon Sep 17 00:00:00 2001 From: Roger Blofeld Date: Sun, 10 Jan 2010 20:52:32 +0100 Subject: hwmon: (adt7462) Fix pin 28 monitoring The ADT7462_PIN28_VOLT value is a 4-bit field, so the corresponding shift must be 4. Signed-off-by: Roger Blofeld Signed-off-by: Jean Delvare --- drivers/hwmon/adt7462.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index a1a7ef14b51..a31e77c776a 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -94,7 +94,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; #define ADT7462_PIN24_SHIFT 6 #define ADT7462_PIN26_VOLT_INPUT 0x08 #define ADT7462_PIN25_VOLT_INPUT 0x20 -#define ADT7462_PIN28_SHIFT 6 /* cfg3 */ +#define ADT7462_PIN28_SHIFT 4 /* cfg3 */ #define ADT7462_PIN28_VOLT 0x5 #define ADT7462_REG_ALARM1 0xB8 -- cgit v1.2.3 From 8ba406be53713efdd705666e2178cfe486fcfb27 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Sun, 10 Jan 2010 20:52:33 +0100 Subject: hwmon: (asus_atk0110) Refactor interface probe code The behaviour is unmodified, this makes easier to override the heuristic (which is probably needed for some boards). Signed-off-by: Luca Tettamanti Signed-off-by: Jean Delvare --- drivers/hwmon/asus_atk0110.c | 98 ++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 5a3ee00c0e7..11739819bad 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -1047,76 +1047,75 @@ remove: return err; } -static int atk_check_old_if(struct atk_data *data) +static int atk_probe_if(struct atk_data *data) { struct device *dev = &data->acpi_dev->dev; acpi_handle ret; acpi_status status; + int err = 0; /* RTMP: read temperature */ status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret); - if (status != AE_OK) { + if (ACPI_SUCCESS(status)) + data->rtmp_handle = ret; + else dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n", acpi_format_exception(status)); - return -ENODEV; - } - data->rtmp_handle = ret; /* RVLT: read voltage */ status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret); - if (status != AE_OK) { + if (ACPI_SUCCESS(status)) + data->rvlt_handle = ret; + else dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n", acpi_format_exception(status)); - return -ENODEV; - } - data->rvlt_handle = ret; /* RFAN: read fan status */ status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret); - if (status != AE_OK) { + if (ACPI_SUCCESS(status)) + data->rfan_handle = ret; + else dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n", acpi_format_exception(status)); - return -ENODEV; - } - data->rfan_handle = ret; - - return 0; -} - -static int atk_check_new_if(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - acpi_handle ret; - acpi_status status; /* Enumeration */ status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret); - if (status != AE_OK) { + if (ACPI_SUCCESS(status)) + data->enumerate_handle = ret; + else dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n", acpi_format_exception(status)); - return -ENODEV; - } - data->enumerate_handle = ret; /* De-multiplexer (read) */ status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret); - if (status != AE_OK) { + if (ACPI_SUCCESS(status)) + data->read_handle = ret; + else dev_dbg(dev, "method " METHOD_READ " not found: %s\n", acpi_format_exception(status)); - return -ENODEV; - } - data->read_handle = ret; /* De-multiplexer (write) */ status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret); - if (status != AE_OK) { - dev_dbg(dev, "method " METHOD_READ " not found: %s\n", + if (ACPI_SUCCESS(status)) + data->write_handle = ret; + else + dev_dbg(dev, "method " METHOD_WRITE " not found: %s\n", acpi_format_exception(status)); - return -ENODEV; - } - data->write_handle = ret; - return 0; + /* Check for hwmon methods: first check "old" style methods; note that + * both may be present: in this case we stick to the old interface; + * analysis of multiple DSDTs indicates that when both interfaces + * are present the new one (GGRP/GITM) is not functional. + */ + if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle) + data->old_interface = true; + else if (data->enumerate_handle && data->read_handle && + data->write_handle) + data->old_interface = false; + else + err = -ENODEV; + + return err; } static int atk_add(struct acpi_device *device) @@ -1155,28 +1154,19 @@ static int atk_add(struct acpi_device *device) } ACPI_FREE(buf.pointer); - /* Check for hwmon methods: first check "old" style methods; note that - * both may be present: in this case we stick to the old interface; - * analysis of multiple DSDTs indicates that when both interfaces - * are present the new one (GGRP/GITM) is not functional. - */ - err = atk_check_old_if(data); - if (!err) { - dev_dbg(&device->dev, "Using old hwmon interface\n"); - data->old_interface = true; - } else { - err = atk_check_new_if(data); - if (err) - goto out; - - dev_dbg(&device->dev, "Using new hwmon interface\n"); - data->old_interface = false; + err = atk_probe_if(data); + if (err) { + dev_err(&device->dev, "No usable hwmon interface detected\n"); + goto out; } - if (data->old_interface) + if (data->old_interface) { + dev_dbg(&device->dev, "Using old hwmon interface\n"); err = atk_enumerate_old_hwmon(data); - else + } else { + dev_dbg(&device->dev, "Using new hwmon interface\n"); err = atk_enumerate_new_hwmon(data); + } if (err < 0) goto out; if (err == 0) { -- cgit v1.2.3 From 7e5eab1128a05b99b8c81c01ff6515a3ca25e5aa Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Sun, 10 Jan 2010 20:52:33 +0100 Subject: hwmon: (asus_atk0110) Add debugfs interface Expose the raw GGRP/GITM interface via debugfs. The hwmon interface is reverse engineered and the driver tends to break on newer boards... Using this interface it's possible to poke directly at the ACPI methods without the need to recompile, reducing the guesswork and the round trips needed to support a new revision of the interface. Signed-off-by: Luca Tettamanti Signed-off-by: Jean Delvare --- drivers/hwmon/asus_atk0110.c | 191 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 11739819bad..6811346c1c6 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -5,6 +5,7 @@ * See COPYING in the top level directory of the kernel tree. */ +#include #include #include #include @@ -101,6 +102,11 @@ struct atk_data { int temperature_count; int fan_count; struct list_head sensor_list; + + struct { + struct dentry *root; + u32 id; + } debugfs; }; @@ -624,6 +630,187 @@ static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) return err; } +#ifdef CONFIG_DEBUG_FS +static int atk_debugfs_gitm_get(void *p, u64 *val) +{ + struct atk_data *data = p; + union acpi_object *ret; + struct atk_acpi_ret_buffer *buf; + int err = 0; + + if (!data->read_handle) + return -ENODEV; + + if (!data->debugfs.id) + return -EINVAL; + + ret = atk_gitm(data, data->debugfs.id); + if (IS_ERR(ret)) + return PTR_ERR(ret); + + buf = (struct atk_acpi_ret_buffer *)ret->buffer.pointer; + if (buf->flags) + *val = buf->value; + else + err = -EIO; + + return err; +} + +DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm, + atk_debugfs_gitm_get, + NULL, + "0x%08llx\n") + +static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj) +{ + int ret = 0; + + switch (obj->type) { + case ACPI_TYPE_INTEGER: + ret = snprintf(buf, sz, "0x%08llx\n", obj->integer.value); + break; + case ACPI_TYPE_STRING: + ret = snprintf(buf, sz, "%s\n", obj->string.pointer); + break; + } + + return ret; +} + +static void atk_pack_print(char *buf, size_t sz, union acpi_object *pack) +{ + int ret; + int i; + + for (i = 0; i < pack->package.count; i++) { + union acpi_object *obj = &pack->package.elements[i]; + + ret = atk_acpi_print(buf, sz, obj); + if (ret >= sz) + break; + buf += ret; + sz -= ret; + } +} + +static int atk_debugfs_ggrp_open(struct inode *inode, struct file *file) +{ + struct atk_data *data = inode->i_private; + char *buf = NULL; + union acpi_object *ret; + u8 cls; + int i; + + if (!data->enumerate_handle) + return -ENODEV; + if (!data->debugfs.id) + return -EINVAL; + + cls = (data->debugfs.id & 0xff000000) >> 24; + ret = atk_ggrp(data, cls); + if (IS_ERR(ret)) + return PTR_ERR(ret); + + for (i = 0; i < ret->package.count; i++) { + union acpi_object *pack = &ret->package.elements[i]; + union acpi_object *id; + + if (pack->type != ACPI_TYPE_PACKAGE) + continue; + if (!pack->package.count) + continue; + id = &pack->package.elements[0]; + if (id->integer.value == data->debugfs.id) { + /* Print the package */ + buf = kzalloc(512, GFP_KERNEL); + if (!buf) { + ACPI_FREE(ret); + return -ENOMEM; + } + atk_pack_print(buf, 512, pack); + break; + } + } + ACPI_FREE(ret); + + if (!buf) + return -EINVAL; + + file->private_data = buf; + + return nonseekable_open(inode, file); +} + +static ssize_t atk_debugfs_ggrp_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + char *str = file->private_data; + size_t len = strlen(str); + + return simple_read_from_buffer(buf, count, pos, str, len); +} + +static int atk_debugfs_ggrp_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static const struct file_operations atk_debugfs_ggrp_fops = { + .read = atk_debugfs_ggrp_read, + .open = atk_debugfs_ggrp_open, + .release = atk_debugfs_ggrp_release, +}; + +static void atk_debugfs_init(struct atk_data *data) +{ + struct dentry *d; + struct dentry *f; + + data->debugfs.id = 0; + + d = debugfs_create_dir("asus_atk0110", NULL); + if (!d || IS_ERR(d)) + return; + + f = debugfs_create_x32("id", S_IRUSR | S_IWUSR, d, &data->debugfs.id); + if (!f || IS_ERR(f)) + goto cleanup; + + f = debugfs_create_file("gitm", S_IRUSR, d, data, + &atk_debugfs_gitm); + if (!f || IS_ERR(f)) + goto cleanup; + + f = debugfs_create_file("ggrp", S_IRUSR, d, data, + &atk_debugfs_ggrp_fops); + if (!f || IS_ERR(f)) + goto cleanup; + + data->debugfs.root = d; + + return; +cleanup: + debugfs_remove_recursive(d); +} + +static void atk_debugfs_cleanup(struct atk_data *data) +{ + debugfs_remove_recursive(data->debugfs.root); +} + +#else /* CONFIG_DEBUG_FS */ + +static void atk_debugfs_init(struct atk_data *data) +{ +} + +static void atk_debugfs_cleanup(struct atk_data *data) +{ +} +#endif + static int atk_add_sensor(struct atk_data *data, union acpi_object *obj) { struct device *dev = &data->acpi_dev->dev; @@ -1180,6 +1367,8 @@ static int atk_add(struct acpi_device *device) if (err) goto cleanup; + atk_debugfs_init(data); + device->driver_data = data; return 0; cleanup: @@ -1198,6 +1387,8 @@ static int atk_remove(struct acpi_device *device, int type) device->driver_data = NULL; + atk_debugfs_cleanup(data); + atk_remove_files(data); atk_free_sensors(data); hwmon_device_unregister(data->hwmon_dev); -- cgit v1.2.3 From c5114a1cd6d84b2b3144c1c3e093c80ca6c30f47 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 10 Jan 2010 20:52:34 +0100 Subject: hwmon: (k10temp) Blacklist more family 10h processors The latest version of the Revision Guide for AMD Family 10h Processors lists two more processor revisions which may be affected by erratum 319. Change the blacklisting code to correctly detect those processors, by implementing AMD's recommended algorithm. Signed-off-by: Clemens Ladisch Signed-off-by: Jean Delvare Cc: Andreas Herrmann --- drivers/hwmon/k10temp.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index d8a26d16d94..4c9d349b3ad 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -33,6 +33,16 @@ static bool force; module_param(force, bool, 0444); MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); +/* CPUID function 0x80000001, ebx */ +#define CPUID_PKGTYPE_MASK 0xf0000000 +#define CPUID_PKGTYPE_F 0x00000000 +#define CPUID_PKGTYPE_AM2R2_AM3 0x10000000 + +/* DRAM controller (PCI function 2) */ +#define REG_DCT0_CONFIG_HIGH 0x094 +#define DDR3_MODE 0x00000100 + +/* miscellaneous (PCI function 3) */ #define REG_HARDWARE_THERMAL_CONTROL 0x64 #define HTC_ENABLE 0x00000001 @@ -85,13 +95,28 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static bool __devinit has_erratum_319(void) +static bool __devinit has_erratum_319(struct pci_dev *pdev) { + u32 pkg_type, reg_dram_cfg; + + if (boot_cpu_data.x86 != 0x10) + return false; + /* - * Erratum 319: The thermal sensor of older Family 10h processors - * (B steppings) may be unreliable. + * Erratum 319: The thermal sensor of Socket F/AM2+ processors + * may be unreliable. */ - return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2; + pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK; + if (pkg_type == CPUID_PKGTYPE_F) + return true; + if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3) + return false; + + /* Differentiate between AM2+ (bad) and AM3 (good) */ + pci_bus_read_config_dword(pdev->bus, + PCI_DEVFN(PCI_SLOT(pdev->devfn), 2), + REG_DCT0_CONFIG_HIGH, ®_dram_cfg); + return !(reg_dram_cfg & DDR3_MODE); } static int __devinit k10temp_probe(struct pci_dev *pdev, @@ -99,9 +124,10 @@ static int __devinit k10temp_probe(struct pci_dev *pdev, { struct device *hwmon_dev; u32 reg_caps, reg_htc; + int unreliable = has_erratum_319(pdev); int err; - if (has_erratum_319() && !force) { + if (unreliable && !force) { dev_err(&pdev->dev, "unreliable CPU thermal sensor; monitoring disabled\n"); err = -ENODEV; @@ -139,7 +165,7 @@ static int __devinit k10temp_probe(struct pci_dev *pdev, } dev_set_drvdata(&pdev->dev, hwmon_dev); - if (has_erratum_319() && force) + if (unreliable && force) dev_warn(&pdev->dev, "unreliable CPU thermal sensor; check erratum 319\n"); return 0; -- cgit v1.2.3 From 1fe63ab47a617ee95f562eaa7ddbbc59981ff8c6 Mon Sep 17 00:00:00 2001 From: Yong Wang Date: Sun, 10 Jan 2010 20:52:34 +0100 Subject: hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs The max junction temperature of Atom N450/D410/D510 CPUs is 100 degrees Celsius. Since these CPUs are always coupled with Intel NM10 chipset in one package, the best way to verify whether an Atom CPU is N450/D410/D510 is to check the host bridge device. Signed-off-by: Yong Wang Acked-by: Huaxu Wan Signed-off-by: Jean Delvare --- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/coretemp.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 46c3c566307..435ae72fc47 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -392,7 +392,7 @@ config SENSORS_GL520SM config SENSORS_CORETEMP tristate "Intel Core/Core2/Atom temperature sensor" - depends on X86 && EXPERIMENTAL + depends on X86 && PCI && EXPERIMENTAL help If you say yes here you get support for the temperature sensor inside your CPU. Most of the family 6 CPUs diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index caef39cda8c..2d7bceeed0b 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,7 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * int usemsr_ee = 1; int err; u32 eax, edx; + struct pci_dev *host_bridge; /* Early chips have no MSR for TjMax */ @@ -168,11 +170,21 @@ static int __devinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device * usemsr_ee = 0; } - /* Atoms seems to have TjMax at 90C */ + /* Atom CPUs */ if (c->x86_model == 0x1c) { usemsr_ee = 0; - tjmax = 90000; + + host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); + + if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL + && (host_bridge->device == 0xa000 /* NM10 based nettop */ + || host_bridge->device == 0xa010)) /* NM10 based netbook */ + tjmax = 100000; + else + tjmax = 90000; + + pci_dev_put(host_bridge); } if ((c->x86_model > 0xe) && (usemsr_ee)) { -- cgit v1.2.3 From 3dd3a156355e7e6bec0dc9a0bbb6eeecbd965d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 10 Jan 2010 20:52:35 +0100 Subject: hwmon: Make PCI device ids constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The id_table field of the struct pci_driver is constant in so it is worth to make pci_device_id also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Signed-off-by: Jean Delvare --- drivers/hwmon/k10temp.c | 2 +- drivers/hwmon/k8temp.c | 2 +- drivers/hwmon/sis5595.c | 2 +- drivers/hwmon/via686a.c | 2 +- drivers/hwmon/vt8231.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index 4c9d349b3ad..099a2138cdf 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -195,7 +195,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev) dev_set_drvdata(&pdev->dev, NULL); } -static struct pci_device_id k10temp_id_table[] = { +static const struct pci_device_id k10temp_id_table[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, {} diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c index 1fe99511184..0ceb6d6200a 100644 --- a/drivers/hwmon/k8temp.c +++ b/drivers/hwmon/k8temp.c @@ -136,7 +136,7 @@ static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0); static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1); static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static struct pci_device_id k8temp_ids[] = { +static const struct pci_device_id k8temp_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, { 0 }, }; diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 12f2e708656..79c2931e300 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -697,7 +697,7 @@ static struct sis5595_data *sis5595_update_device(struct device *dev) return data; } -static struct pci_device_id sis5595_pci_ids[] = { +static const struct pci_device_id sis5595_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { 0, } }; diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 39e82a492f2..f397ce7ad59 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -767,7 +767,7 @@ static struct via686a_data *via686a_update_device(struct device *dev) return data; } -static struct pci_device_id via686a_pci_ids[] = { +static const struct pci_device_id via686a_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) }, { 0, } }; diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 470a1226ba2..d47b4c9949c 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -697,7 +697,7 @@ static struct platform_driver vt8231_driver = { .remove = __devexit_p(vt8231_remove), }; -static struct pci_device_id vt8231_pci_ids[] = { +static const struct pci_device_id vt8231_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) }, { 0, } }; -- cgit v1.2.3 From 804c7559e9376c3ba78ae15a30337b1e24f8ae80 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 8 Jan 2010 15:58:49 -0500 Subject: drm/radeon/kms: add additional safe regs for r4xx/rs6xx and r5xx - r4xx/rs6xx: add support for extended pixel shader instruction/temp regs - r5xx: add SM3 regs Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/Makefile | 5 + drivers/gpu/drm/radeon/r420.c | 9 +- drivers/gpu/drm/radeon/reg_srcs/r420 | 795 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/reg_srcs/rs600 | 68 ++- drivers/gpu/drm/radeon/reg_srcs/rv515 | 6 + 5 files changed, 881 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/radeon/reg_srcs/r420 (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index b5f5fe75e6a..1cc7b937b1e 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -24,6 +24,9 @@ $(obj)/rv515_reg_safe.h: $(src)/reg_srcs/rv515 $(obj)/mkregtable $(obj)/r300_reg_safe.h: $(src)/reg_srcs/r300 $(obj)/mkregtable $(call if_changed,mkregtable) +$(obj)/r420_reg_safe.h: $(src)/reg_srcs/r420 $(obj)/mkregtable + $(call if_changed,mkregtable) + $(obj)/rs600_reg_safe.h: $(src)/reg_srcs/rs600 $(obj)/mkregtable $(call if_changed,mkregtable) @@ -35,6 +38,8 @@ $(obj)/rv515.o: $(obj)/rv515_reg_safe.h $(obj)/r300.o: $(obj)/r300_reg_safe.h +$(obj)/r420.o: $(obj)/r420_reg_safe.h + $(obj)/rs600.o: $(obj)/rs600_reg_safe.h radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 1d4d16ed7db..053404e71a9 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -32,6 +32,13 @@ #include "atom.h" #include "r100d.h" #include "r420d.h" +#include "r420_reg_safe.h" + +static void r420_set_reg_safe(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = r420_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r420_reg_safe_bm); +} int r420_mc_init(struct radeon_device *rdev) { @@ -378,7 +385,7 @@ int r420_init(struct radeon_device *rdev) if (r) return r; } - r300_set_reg_safe(rdev); + r420_set_reg_safe(rdev); rdev->accel_working = true; r = r420_startup(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/reg_srcs/r420 b/drivers/gpu/drm/radeon/reg_srcs/r420 new file mode 100644 index 00000000000..989f7a02083 --- /dev/null +++ b/drivers/gpu/drm/radeon/reg_srcs/r420 @@ -0,0 +1,795 @@ +r420 0x4f60 +0x1434 SRC_Y_X +0x1438 DST_Y_X +0x143C DST_HEIGHT_WIDTH +0x146C DP_GUI_MASTER_CNTL +0x1474 BRUSH_Y_X +0x1478 DP_BRUSH_BKGD_CLR +0x147C DP_BRUSH_FRGD_CLR +0x1480 BRUSH_DATA0 +0x1484 BRUSH_DATA1 +0x1598 DST_WIDTH_HEIGHT +0x15C0 CLR_CMP_CNTL +0x15C4 CLR_CMP_CLR_SRC +0x15C8 CLR_CMP_CLR_DST +0x15CC CLR_CMP_MSK +0x15D8 DP_SRC_FRGD_CLR +0x15DC DP_SRC_BKGD_CLR +0x1600 DST_LINE_START +0x1604 DST_LINE_END +0x1608 DST_LINE_PATCOUNT +0x16C0 DP_CNTL +0x16CC DP_WRITE_MSK +0x16D0 DP_CNTL_XDIR_YDIR_YMAJOR +0x16E8 DEFAULT_SC_BOTTOM_RIGHT +0x16EC SC_TOP_LEFT +0x16F0 SC_BOTTOM_RIGHT +0x16F4 SRC_SC_BOTTOM_RIGHT +0x1714 DSTCACHE_CTLSTAT +0x1720 WAIT_UNTIL +0x172C RBBM_GUICNTL +0x1D98 VAP_VPORT_XSCALE +0x1D9C VAP_VPORT_XOFFSET +0x1DA0 VAP_VPORT_YSCALE +0x1DA4 VAP_VPORT_YOFFSET +0x1DA8 VAP_VPORT_ZSCALE +0x1DAC VAP_VPORT_ZOFFSET +0x2080 VAP_CNTL +0x2090 VAP_OUT_VTX_FMT_0 +0x2094 VAP_OUT_VTX_FMT_1 +0x20B0 VAP_VTE_CNTL +0x2138 VAP_VF_MIN_VTX_INDX +0x2140 VAP_CNTL_STATUS +0x2150 VAP_PROG_STREAM_CNTL_0 +0x2154 VAP_PROG_STREAM_CNTL_1 +0x2158 VAP_PROG_STREAM_CNTL_2 +0x215C VAP_PROG_STREAM_CNTL_3 +0x2160 VAP_PROG_STREAM_CNTL_4 +0x2164 VAP_PROG_STREAM_CNTL_5 +0x2168 VAP_PROG_STREAM_CNTL_6 +0x216C VAP_PROG_STREAM_CNTL_7 +0x2180 VAP_VTX_STATE_CNTL +0x2184 VAP_VSM_VTX_ASSM +0x2188 VAP_VTX_STATE_IND_REG_0 +0x218C VAP_VTX_STATE_IND_REG_1 +0x2190 VAP_VTX_STATE_IND_REG_2 +0x2194 VAP_VTX_STATE_IND_REG_3 +0x2198 VAP_VTX_STATE_IND_REG_4 +0x219C VAP_VTX_STATE_IND_REG_5 +0x21A0 VAP_VTX_STATE_IND_REG_6 +0x21A4 VAP_VTX_STATE_IND_REG_7 +0x21A8 VAP_VTX_STATE_IND_REG_8 +0x21AC VAP_VTX_STATE_IND_REG_9 +0x21B0 VAP_VTX_STATE_IND_REG_10 +0x21B4 VAP_VTX_STATE_IND_REG_11 +0x21B8 VAP_VTX_STATE_IND_REG_12 +0x21BC VAP_VTX_STATE_IND_REG_13 +0x21C0 VAP_VTX_STATE_IND_REG_14 +0x21C4 VAP_VTX_STATE_IND_REG_15 +0x21DC VAP_PSC_SGN_NORM_CNTL +0x21E0 VAP_PROG_STREAM_CNTL_EXT_0 +0x21E4 VAP_PROG_STREAM_CNTL_EXT_1 +0x21E8 VAP_PROG_STREAM_CNTL_EXT_2 +0x21EC VAP_PROG_STREAM_CNTL_EXT_3 +0x21F0 VAP_PROG_STREAM_CNTL_EXT_4 +0x21F4 VAP_PROG_STREAM_CNTL_EXT_5 +0x21F8 VAP_PROG_STREAM_CNTL_EXT_6 +0x21FC VAP_PROG_STREAM_CNTL_EXT_7 +0x2200 VAP_PVS_VECTOR_INDX_REG +0x2204 VAP_PVS_VECTOR_DATA_REG +0x2208 VAP_PVS_VECTOR_DATA_REG_128 +0x221C VAP_CLIP_CNTL +0x2220 VAP_GB_VERT_CLIP_ADJ +0x2224 VAP_GB_VERT_DISC_ADJ +0x2228 VAP_GB_HORZ_CLIP_ADJ +0x222C VAP_GB_HORZ_DISC_ADJ +0x2230 VAP_PVS_FLOW_CNTL_ADDRS_0 +0x2234 VAP_PVS_FLOW_CNTL_ADDRS_1 +0x2238 VAP_PVS_FLOW_CNTL_ADDRS_2 +0x223C VAP_PVS_FLOW_CNTL_ADDRS_3 +0x2240 VAP_PVS_FLOW_CNTL_ADDRS_4 +0x2244 VAP_PVS_FLOW_CNTL_ADDRS_5 +0x2248 VAP_PVS_FLOW_CNTL_ADDRS_6 +0x224C VAP_PVS_FLOW_CNTL_ADDRS_7 +0x2250 VAP_PVS_FLOW_CNTL_ADDRS_8 +0x2254 VAP_PVS_FLOW_CNTL_ADDRS_9 +0x2258 VAP_PVS_FLOW_CNTL_ADDRS_10 +0x225C VAP_PVS_FLOW_CNTL_ADDRS_11 +0x2260 VAP_PVS_FLOW_CNTL_ADDRS_12 +0x2264 VAP_PVS_FLOW_CNTL_ADDRS_13 +0x2268 VAP_PVS_FLOW_CNTL_ADDRS_14 +0x226C VAP_PVS_FLOW_CNTL_ADDRS_15 +0x2284 VAP_PVS_STATE_FLUSH_REG +0x2288 VAP_PVS_VTX_TIMEOUT_REG +0x2290 VAP_PVS_FLOW_CNTL_LOOP_INDEX_0 +0x2294 VAP_PVS_FLOW_CNTL_LOOP_INDEX_1 +0x2298 VAP_PVS_FLOW_CNTL_LOOP_INDEX_2 +0x229C VAP_PVS_FLOW_CNTL_LOOP_INDEX_3 +0x22A0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_4 +0x22A4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_5 +0x22A8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_6 +0x22AC VAP_PVS_FLOW_CNTL_LOOP_INDEX_7 +0x22B0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_8 +0x22B4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_9 +0x22B8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_10 +0x22BC VAP_PVS_FLOW_CNTL_LOOP_INDEX_11 +0x22C0 VAP_PVS_FLOW_CNTL_LOOP_INDEX_12 +0x22C4 VAP_PVS_FLOW_CNTL_LOOP_INDEX_13 +0x22C8 VAP_PVS_FLOW_CNTL_LOOP_INDEX_14 +0x22CC VAP_PVS_FLOW_CNTL_LOOP_INDEX_15 +0x22D0 VAP_PVS_CODE_CNTL_0 +0x22D4 VAP_PVS_CONST_CNTL +0x22D8 VAP_PVS_CODE_CNTL_1 +0x22DC VAP_PVS_FLOW_CNTL_OPC +0x342C RB2D_DSTCACHE_CTLSTAT +0x4000 GB_VAP_RASTER_VTX_FMT_0 +0x4004 GB_VAP_RASTER_VTX_FMT_1 +0x4008 GB_ENABLE +0x401C GB_SELECT +0x4020 GB_AA_CONFIG +0x4024 GB_FIFO_SIZE +0x4100 TX_INVALTAGS +0x4200 GA_POINT_S0 +0x4204 GA_POINT_T0 +0x4208 GA_POINT_S1 +0x420C GA_POINT_T1 +0x4214 GA_TRIANGLE_STIPPLE +0x421C GA_POINT_SIZE +0x4230 GA_POINT_MINMAX +0x4234 GA_LINE_CNTL +0x4238 GA_LINE_STIPPLE_CONFIG +0x4260 GA_LINE_STIPPLE_VALUE +0x4264 GA_LINE_S0 +0x4268 GA_LINE_S1 +0x4278 GA_COLOR_CONTROL +0x427C GA_SOLID_RG +0x4280 GA_SOLID_BA +0x4288 GA_POLY_MODE +0x428C GA_ROUND_MODE +0x4290 GA_OFFSET +0x4294 GA_FOG_SCALE +0x4298 GA_FOG_OFFSET +0x42A0 SU_TEX_WRAP +0x42A4 SU_POLY_OFFSET_FRONT_SCALE +0x42A8 SU_POLY_OFFSET_FRONT_OFFSET +0x42AC SU_POLY_OFFSET_BACK_SCALE +0x42B0 SU_POLY_OFFSET_BACK_OFFSET +0x42B4 SU_POLY_OFFSET_ENABLE +0x42B8 SU_CULL_MODE +0x42C0 SU_DEPTH_SCALE +0x42C4 SU_DEPTH_OFFSET +0x42C8 SU_REG_DEST +0x4300 RS_COUNT +0x4304 RS_INST_COUNT +0x4310 RS_IP_0 +0x4314 RS_IP_1 +0x4318 RS_IP_2 +0x431C RS_IP_3 +0x4320 RS_IP_4 +0x4324 RS_IP_5 +0x4328 RS_IP_6 +0x432C RS_IP_7 +0x4330 RS_INST_0 +0x4334 RS_INST_1 +0x4338 RS_INST_2 +0x433C RS_INST_3 +0x4340 RS_INST_4 +0x4344 RS_INST_5 +0x4348 RS_INST_6 +0x434C RS_INST_7 +0x4350 RS_INST_8 +0x4354 RS_INST_9 +0x4358 RS_INST_10 +0x435C RS_INST_11 +0x4360 RS_INST_12 +0x4364 RS_INST_13 +0x4368 RS_INST_14 +0x436C RS_INST_15 +0x43A4 SC_HYPERZ_EN +0x43A8 SC_EDGERULE +0x43B0 SC_CLIP_0_A +0x43B4 SC_CLIP_0_B +0x43B8 SC_CLIP_1_A +0x43BC SC_CLIP_1_B +0x43C0 SC_CLIP_2_A +0x43C4 SC_CLIP_2_B +0x43C8 SC_CLIP_3_A +0x43CC SC_CLIP_3_B +0x43D0 SC_CLIP_RULE +0x43E0 SC_SCISSOR0 +0x43E8 SC_SCREENDOOR +0x4440 TX_FILTER1_0 +0x4444 TX_FILTER1_1 +0x4448 TX_FILTER1_2 +0x444C TX_FILTER1_3 +0x4450 TX_FILTER1_4 +0x4454 TX_FILTER1_5 +0x4458 TX_FILTER1_6 +0x445C TX_FILTER1_7 +0x4460 TX_FILTER1_8 +0x4464 TX_FILTER1_9 +0x4468 TX_FILTER1_10 +0x446C TX_FILTER1_11 +0x4470 TX_FILTER1_12 +0x4474 TX_FILTER1_13 +0x4478 TX_FILTER1_14 +0x447C TX_FILTER1_15 +0x4580 TX_CHROMA_KEY_0 +0x4584 TX_CHROMA_KEY_1 +0x4588 TX_CHROMA_KEY_2 +0x458C TX_CHROMA_KEY_3 +0x4590 TX_CHROMA_KEY_4 +0x4594 TX_CHROMA_KEY_5 +0x4598 TX_CHROMA_KEY_6 +0x459C TX_CHROMA_KEY_7 +0x45A0 TX_CHROMA_KEY_8 +0x45A4 TX_CHROMA_KEY_9 +0x45A8 TX_CHROMA_KEY_10 +0x45AC TX_CHROMA_KEY_11 +0x45B0 TX_CHROMA_KEY_12 +0x45B4 TX_CHROMA_KEY_13 +0x45B8 TX_CHROMA_KEY_14 +0x45BC TX_CHROMA_KEY_15 +0x45C0 TX_BORDER_COLOR_0 +0x45C4 TX_BORDER_COLOR_1 +0x45C8 TX_BORDER_COLOR_2 +0x45CC TX_BORDER_COLOR_3 +0x45D0 TX_BORDER_COLOR_4 +0x45D4 TX_BORDER_COLOR_5 +0x45D8 TX_BORDER_COLOR_6 +0x45DC TX_BORDER_COLOR_7 +0x45E0 TX_BORDER_COLOR_8 +0x45E4 TX_BORDER_COLOR_9 +0x45E8 TX_BORDER_COLOR_10 +0x45EC TX_BORDER_COLOR_11 +0x45F0 TX_BORDER_COLOR_12 +0x45F4 TX_BORDER_COLOR_13 +0x45F8 TX_BORDER_COLOR_14 +0x45FC TX_BORDER_COLOR_15 +0x4600 US_CONFIG +0x4604 US_PIXSIZE +0x4608 US_CODE_OFFSET +0x460C US_RESET +0x4610 US_CODE_ADDR_0 +0x4614 US_CODE_ADDR_1 +0x4618 US_CODE_ADDR_2 +0x461C US_CODE_ADDR_3 +0x4620 US_TEX_INST_0 +0x4624 US_TEX_INST_1 +0x4628 US_TEX_INST_2 +0x462C US_TEX_INST_3 +0x4630 US_TEX_INST_4 +0x4634 US_TEX_INST_5 +0x4638 US_TEX_INST_6 +0x463C US_TEX_INST_7 +0x4640 US_TEX_INST_8 +0x4644 US_TEX_INST_9 +0x4648 US_TEX_INST_10 +0x464C US_TEX_INST_11 +0x4650 US_TEX_INST_12 +0x4654 US_TEX_INST_13 +0x4658 US_TEX_INST_14 +0x465C US_TEX_INST_15 +0x4660 US_TEX_INST_16 +0x4664 US_TEX_INST_17 +0x4668 US_TEX_INST_18 +0x466C US_TEX_INST_19 +0x4670 US_TEX_INST_20 +0x4674 US_TEX_INST_21 +0x4678 US_TEX_INST_22 +0x467C US_TEX_INST_23 +0x4680 US_TEX_INST_24 +0x4684 US_TEX_INST_25 +0x4688 US_TEX_INST_26 +0x468C US_TEX_INST_27 +0x4690 US_TEX_INST_28 +0x4694 US_TEX_INST_29 +0x4698 US_TEX_INST_30 +0x469C US_TEX_INST_31 +0x46A4 US_OUT_FMT_0 +0x46A8 US_OUT_FMT_1 +0x46AC US_OUT_FMT_2 +0x46B0 US_OUT_FMT_3 +0x46B4 US_W_FMT +0x46B8 US_CODE_BANK +0x46BC US_CODE_EXT +0x46C0 US_ALU_RGB_ADDR_0 +0x46C4 US_ALU_RGB_ADDR_1 +0x46C8 US_ALU_RGB_ADDR_2 +0x46CC US_ALU_RGB_ADDR_3 +0x46D0 US_ALU_RGB_ADDR_4 +0x46D4 US_ALU_RGB_ADDR_5 +0x46D8 US_ALU_RGB_ADDR_6 +0x46DC US_ALU_RGB_ADDR_7 +0x46E0 US_ALU_RGB_ADDR_8 +0x46E4 US_ALU_RGB_ADDR_9 +0x46E8 US_ALU_RGB_ADDR_10 +0x46EC US_ALU_RGB_ADDR_11 +0x46F0 US_ALU_RGB_ADDR_12 +0x46F4 US_ALU_RGB_ADDR_13 +0x46F8 US_ALU_RGB_ADDR_14 +0x46FC US_ALU_RGB_ADDR_15 +0x4700 US_ALU_RGB_ADDR_16 +0x4704 US_ALU_RGB_ADDR_17 +0x4708 US_ALU_RGB_ADDR_18 +0x470C US_ALU_RGB_ADDR_19 +0x4710 US_ALU_RGB_ADDR_20 +0x4714 US_ALU_RGB_ADDR_21 +0x4718 US_ALU_RGB_ADDR_22 +0x471C US_ALU_RGB_ADDR_23 +0x4720 US_ALU_RGB_ADDR_24 +0x4724 US_ALU_RGB_ADDR_25 +0x4728 US_ALU_RGB_ADDR_26 +0x472C US_ALU_RGB_ADDR_27 +0x4730 US_ALU_RGB_ADDR_28 +0x4734 US_ALU_RGB_ADDR_29 +0x4738 US_ALU_RGB_ADDR_30 +0x473C US_ALU_RGB_ADDR_31 +0x4740 US_ALU_RGB_ADDR_32 +0x4744 US_ALU_RGB_ADDR_33 +0x4748 US_ALU_RGB_ADDR_34 +0x474C US_ALU_RGB_ADDR_35 +0x4750 US_ALU_RGB_ADDR_36 +0x4754 US_ALU_RGB_ADDR_37 +0x4758 US_ALU_RGB_ADDR_38 +0x475C US_ALU_RGB_ADDR_39 +0x4760 US_ALU_RGB_ADDR_40 +0x4764 US_ALU_RGB_ADDR_41 +0x4768 US_ALU_RGB_ADDR_42 +0x476C US_ALU_RGB_ADDR_43 +0x4770 US_ALU_RGB_ADDR_44 +0x4774 US_ALU_RGB_ADDR_45 +0x4778 US_ALU_RGB_ADDR_46 +0x477C US_ALU_RGB_ADDR_47 +0x4780 US_ALU_RGB_ADDR_48 +0x4784 US_ALU_RGB_ADDR_49 +0x4788 US_ALU_RGB_ADDR_50 +0x478C US_ALU_RGB_ADDR_51 +0x4790 US_ALU_RGB_ADDR_52 +0x4794 US_ALU_RGB_ADDR_53 +0x4798 US_ALU_RGB_ADDR_54 +0x479C US_ALU_RGB_ADDR_55 +0x47A0 US_ALU_RGB_ADDR_56 +0x47A4 US_ALU_RGB_ADDR_57 +0x47A8 US_ALU_RGB_ADDR_58 +0x47AC US_ALU_RGB_ADDR_59 +0x47B0 US_ALU_RGB_ADDR_60 +0x47B4 US_ALU_RGB_ADDR_61 +0x47B8 US_ALU_RGB_ADDR_62 +0x47BC US_ALU_RGB_ADDR_63 +0x47C0 US_ALU_ALPHA_ADDR_0 +0x47C4 US_ALU_ALPHA_ADDR_1 +0x47C8 US_ALU_ALPHA_ADDR_2 +0x47CC US_ALU_ALPHA_ADDR_3 +0x47D0 US_ALU_ALPHA_ADDR_4 +0x47D4 US_ALU_ALPHA_ADDR_5 +0x47D8 US_ALU_ALPHA_ADDR_6 +0x47DC US_ALU_ALPHA_ADDR_7 +0x47E0 US_ALU_ALPHA_ADDR_8 +0x47E4 US_ALU_ALPHA_ADDR_9 +0x47E8 US_ALU_ALPHA_ADDR_10 +0x47EC US_ALU_ALPHA_ADDR_11 +0x47F0 US_ALU_ALPHA_ADDR_12 +0x47F4 US_ALU_ALPHA_ADDR_13 +0x47F8 US_ALU_ALPHA_ADDR_14 +0x47FC US_ALU_ALPHA_ADDR_15 +0x4800 US_ALU_ALPHA_ADDR_16 +0x4804 US_ALU_ALPHA_ADDR_17 +0x4808 US_ALU_ALPHA_ADDR_18 +0x480C US_ALU_ALPHA_ADDR_19 +0x4810 US_ALU_ALPHA_ADDR_20 +0x4814 US_ALU_ALPHA_ADDR_21 +0x4818 US_ALU_ALPHA_ADDR_22 +0x481C US_ALU_ALPHA_ADDR_23 +0x4820 US_ALU_ALPHA_ADDR_24 +0x4824 US_ALU_ALPHA_ADDR_25 +0x4828 US_ALU_ALPHA_ADDR_26 +0x482C US_ALU_ALPHA_ADDR_27 +0x4830 US_ALU_ALPHA_ADDR_28 +0x4834 US_ALU_ALPHA_ADDR_29 +0x4838 US_ALU_ALPHA_ADDR_30 +0x483C US_ALU_ALPHA_ADDR_31 +0x4840 US_ALU_ALPHA_ADDR_32 +0x4844 US_ALU_ALPHA_ADDR_33 +0x4848 US_ALU_ALPHA_ADDR_34 +0x484C US_ALU_ALPHA_ADDR_35 +0x4850 US_ALU_ALPHA_ADDR_36 +0x4854 US_ALU_ALPHA_ADDR_37 +0x4858 US_ALU_ALPHA_ADDR_38 +0x485C US_ALU_ALPHA_ADDR_39 +0x4860 US_ALU_ALPHA_ADDR_40 +0x4864 US_ALU_ALPHA_ADDR_41 +0x4868 US_ALU_ALPHA_ADDR_42 +0x486C US_ALU_ALPHA_ADDR_43 +0x4870 US_ALU_ALPHA_ADDR_44 +0x4874 US_ALU_ALPHA_ADDR_45 +0x4878 US_ALU_ALPHA_ADDR_46 +0x487C US_ALU_ALPHA_ADDR_47 +0x4880 US_ALU_ALPHA_ADDR_48 +0x4884 US_ALU_ALPHA_ADDR_49 +0x4888 US_ALU_ALPHA_ADDR_50 +0x488C US_ALU_ALPHA_ADDR_51 +0x4890 US_ALU_ALPHA_ADDR_52 +0x4894 US_ALU_ALPHA_ADDR_53 +0x4898 US_ALU_ALPHA_ADDR_54 +0x489C US_ALU_ALPHA_ADDR_55 +0x48A0 US_ALU_ALPHA_ADDR_56 +0x48A4 US_ALU_ALPHA_ADDR_57 +0x48A8 US_ALU_ALPHA_ADDR_58 +0x48AC US_ALU_ALPHA_ADDR_59 +0x48B0 US_ALU_ALPHA_ADDR_60 +0x48B4 US_ALU_ALPHA_ADDR_61 +0x48B8 US_ALU_ALPHA_ADDR_62 +0x48BC US_ALU_ALPHA_ADDR_63 +0x48C0 US_ALU_RGB_INST_0 +0x48C4 US_ALU_RGB_INST_1 +0x48C8 US_ALU_RGB_INST_2 +0x48CC US_ALU_RGB_INST_3 +0x48D0 US_ALU_RGB_INST_4 +0x48D4 US_ALU_RGB_INST_5 +0x48D8 US_ALU_RGB_INST_6 +0x48DC US_ALU_RGB_INST_7 +0x48E0 US_ALU_RGB_INST_8 +0x48E4 US_ALU_RGB_INST_9 +0x48E8 US_ALU_RGB_INST_10 +0x48EC US_ALU_RGB_INST_11 +0x48F0 US_ALU_RGB_INST_12 +0x48F4 US_ALU_RGB_INST_13 +0x48F8 US_ALU_RGB_INST_14 +0x48FC US_ALU_RGB_INST_15 +0x4900 US_ALU_RGB_INST_16 +0x4904 US_ALU_RGB_INST_17 +0x4908 US_ALU_RGB_INST_18 +0x490C US_ALU_RGB_INST_19 +0x4910 US_ALU_RGB_INST_20 +0x4914 US_ALU_RGB_INST_21 +0x4918 US_ALU_RGB_INST_22 +0x491C US_ALU_RGB_INST_23 +0x4920 US_ALU_RGB_INST_24 +0x4924 US_ALU_RGB_INST_25 +0x4928 US_ALU_RGB_INST_26 +0x492C US_ALU_RGB_INST_27 +0x4930 US_ALU_RGB_INST_28 +0x4934 US_ALU_RGB_INST_29 +0x4938 US_ALU_RGB_INST_30 +0x493C US_ALU_RGB_INST_31 +0x4940 US_ALU_RGB_INST_32 +0x4944 US_ALU_RGB_INST_33 +0x4948 US_ALU_RGB_INST_34 +0x494C US_ALU_RGB_INST_35 +0x4950 US_ALU_RGB_INST_36 +0x4954 US_ALU_RGB_INST_37 +0x4958 US_ALU_RGB_INST_38 +0x495C US_ALU_RGB_INST_39 +0x4960 US_ALU_RGB_INST_40 +0x4964 US_ALU_RGB_INST_41 +0x4968 US_ALU_RGB_INST_42 +0x496C US_ALU_RGB_INST_43 +0x4970 US_ALU_RGB_INST_44 +0x4974 US_ALU_RGB_INST_45 +0x4978 US_ALU_RGB_INST_46 +0x497C US_ALU_RGB_INST_47 +0x4980 US_ALU_RGB_INST_48 +0x4984 US_ALU_RGB_INST_49 +0x4988 US_ALU_RGB_INST_50 +0x498C US_ALU_RGB_INST_51 +0x4990 US_ALU_RGB_INST_52 +0x4994 US_ALU_RGB_INST_53 +0x4998 US_ALU_RGB_INST_54 +0x499C US_ALU_RGB_INST_55 +0x49A0 US_ALU_RGB_INST_56 +0x49A4 US_ALU_RGB_INST_57 +0x49A8 US_ALU_RGB_INST_58 +0x49AC US_ALU_RGB_INST_59 +0x49B0 US_ALU_RGB_INST_60 +0x49B4 US_ALU_RGB_INST_61 +0x49B8 US_ALU_RGB_INST_62 +0x49BC US_ALU_RGB_INST_63 +0x49C0 US_ALU_ALPHA_INST_0 +0x49C4 US_ALU_ALPHA_INST_1 +0x49C8 US_ALU_ALPHA_INST_2 +0x49CC US_ALU_ALPHA_INST_3 +0x49D0 US_ALU_ALPHA_INST_4 +0x49D4 US_ALU_ALPHA_INST_5 +0x49D8 US_ALU_ALPHA_INST_6 +0x49DC US_ALU_ALPHA_INST_7 +0x49E0 US_ALU_ALPHA_INST_8 +0x49E4 US_ALU_ALPHA_INST_9 +0x49E8 US_ALU_ALPHA_INST_10 +0x49EC US_ALU_ALPHA_INST_11 +0x49F0 US_ALU_ALPHA_INST_12 +0x49F4 US_ALU_ALPHA_INST_13 +0x49F8 US_ALU_ALPHA_INST_14 +0x49FC US_ALU_ALPHA_INST_15 +0x4A00 US_ALU_ALPHA_INST_16 +0x4A04 US_ALU_ALPHA_INST_17 +0x4A08 US_ALU_ALPHA_INST_18 +0x4A0C US_ALU_ALPHA_INST_19 +0x4A10 US_ALU_ALPHA_INST_20 +0x4A14 US_ALU_ALPHA_INST_21 +0x4A18 US_ALU_ALPHA_INST_22 +0x4A1C US_ALU_ALPHA_INST_23 +0x4A20 US_ALU_ALPHA_INST_24 +0x4A24 US_ALU_ALPHA_INST_25 +0x4A28 US_ALU_ALPHA_INST_26 +0x4A2C US_ALU_ALPHA_INST_27 +0x4A30 US_ALU_ALPHA_INST_28 +0x4A34 US_ALU_ALPHA_INST_29 +0x4A38 US_ALU_ALPHA_INST_30 +0x4A3C US_ALU_ALPHA_INST_31 +0x4A40 US_ALU_ALPHA_INST_32 +0x4A44 US_ALU_ALPHA_INST_33 +0x4A48 US_ALU_ALPHA_INST_34 +0x4A4C US_ALU_ALPHA_INST_35 +0x4A50 US_ALU_ALPHA_INST_36 +0x4A54 US_ALU_ALPHA_INST_37 +0x4A58 US_ALU_ALPHA_INST_38 +0x4A5C US_ALU_ALPHA_INST_39 +0x4A60 US_ALU_ALPHA_INST_40 +0x4A64 US_ALU_ALPHA_INST_41 +0x4A68 US_ALU_ALPHA_INST_42 +0x4A6C US_ALU_ALPHA_INST_43 +0x4A70 US_ALU_ALPHA_INST_44 +0x4A74 US_ALU_ALPHA_INST_45 +0x4A78 US_ALU_ALPHA_INST_46 +0x4A7C US_ALU_ALPHA_INST_47 +0x4A80 US_ALU_ALPHA_INST_48 +0x4A84 US_ALU_ALPHA_INST_49 +0x4A88 US_ALU_ALPHA_INST_50 +0x4A8C US_ALU_ALPHA_INST_51 +0x4A90 US_ALU_ALPHA_INST_52 +0x4A94 US_ALU_ALPHA_INST_53 +0x4A98 US_ALU_ALPHA_INST_54 +0x4A9C US_ALU_ALPHA_INST_55 +0x4AA0 US_ALU_ALPHA_INST_56 +0x4AA4 US_ALU_ALPHA_INST_57 +0x4AA8 US_ALU_ALPHA_INST_58 +0x4AAC US_ALU_ALPHA_INST_59 +0x4AB0 US_ALU_ALPHA_INST_60 +0x4AB4 US_ALU_ALPHA_INST_61 +0x4AB8 US_ALU_ALPHA_INST_62 +0x4ABC US_ALU_ALPHA_INST_63 +0x4AC0 US_ALU_EXT_ADDR_0 +0x4AC4 US_ALU_EXT_ADDR_1 +0x4AC8 US_ALU_EXT_ADDR_2 +0x4ACC US_ALU_EXT_ADDR_3 +0x4AD0 US_ALU_EXT_ADDR_4 +0x4AD4 US_ALU_EXT_ADDR_5 +0x4AD8 US_ALU_EXT_ADDR_6 +0x4ADC US_ALU_EXT_ADDR_7 +0x4AE0 US_ALU_EXT_ADDR_8 +0x4AE4 US_ALU_EXT_ADDR_9 +0x4AE8 US_ALU_EXT_ADDR_10 +0x4AEC US_ALU_EXT_ADDR_11 +0x4AF0 US_ALU_EXT_ADDR_12 +0x4AF4 US_ALU_EXT_ADDR_13 +0x4AF8 US_ALU_EXT_ADDR_14 +0x4AFC US_ALU_EXT_ADDR_15 +0x4B00 US_ALU_EXT_ADDR_16 +0x4B04 US_ALU_EXT_ADDR_17 +0x4B08 US_ALU_EXT_ADDR_18 +0x4B0C US_ALU_EXT_ADDR_19 +0x4B10 US_ALU_EXT_ADDR_20 +0x4B14 US_ALU_EXT_ADDR_21 +0x4B18 US_ALU_EXT_ADDR_22 +0x4B1C US_ALU_EXT_ADDR_23 +0x4B20 US_ALU_EXT_ADDR_24 +0x4B24 US_ALU_EXT_ADDR_25 +0x4B28 US_ALU_EXT_ADDR_26 +0x4B2C US_ALU_EXT_ADDR_27 +0x4B30 US_ALU_EXT_ADDR_28 +0x4B34 US_ALU_EXT_ADDR_29 +0x4B38 US_ALU_EXT_ADDR_30 +0x4B3C US_ALU_EXT_ADDR_31 +0x4B40 US_ALU_EXT_ADDR_32 +0x4B44 US_ALU_EXT_ADDR_33 +0x4B48 US_ALU_EXT_ADDR_34 +0x4B4C US_ALU_EXT_ADDR_35 +0x4B50 US_ALU_EXT_ADDR_36 +0x4B54 US_ALU_EXT_ADDR_37 +0x4B58 US_ALU_EXT_ADDR_38 +0x4B5C US_ALU_EXT_ADDR_39 +0x4B60 US_ALU_EXT_ADDR_40 +0x4B64 US_ALU_EXT_ADDR_41 +0x4B68 US_ALU_EXT_ADDR_42 +0x4B6C US_ALU_EXT_ADDR_43 +0x4B70 US_ALU_EXT_ADDR_44 +0x4B74 US_ALU_EXT_ADDR_45 +0x4B78 US_ALU_EXT_ADDR_46 +0x4B7C US_ALU_EXT_ADDR_47 +0x4B80 US_ALU_EXT_ADDR_48 +0x4B84 US_ALU_EXT_ADDR_49 +0x4B88 US_ALU_EXT_ADDR_50 +0x4B8C US_ALU_EXT_ADDR_51 +0x4B90 US_ALU_EXT_ADDR_52 +0x4B94 US_ALU_EXT_ADDR_53 +0x4B98 US_ALU_EXT_ADDR_54 +0x4B9C US_ALU_EXT_ADDR_55 +0x4BA0 US_ALU_EXT_ADDR_56 +0x4BA4 US_ALU_EXT_ADDR_57 +0x4BA8 US_ALU_EXT_ADDR_58 +0x4BAC US_ALU_EXT_ADDR_59 +0x4BB0 US_ALU_EXT_ADDR_60 +0x4BB4 US_ALU_EXT_ADDR_61 +0x4BB8 US_ALU_EXT_ADDR_62 +0x4BBC US_ALU_EXT_ADDR_63 +0x4BC0 FG_FOG_BLEND +0x4BC4 FG_FOG_FACTOR +0x4BC8 FG_FOG_COLOR_R +0x4BCC FG_FOG_COLOR_G +0x4BD0 FG_FOG_COLOR_B +0x4BD4 FG_ALPHA_FUNC +0x4BD8 FG_DEPTH_SRC +0x4C00 US_ALU_CONST_R_0 +0x4C04 US_ALU_CONST_G_0 +0x4C08 US_ALU_CONST_B_0 +0x4C0C US_ALU_CONST_A_0 +0x4C10 US_ALU_CONST_R_1 +0x4C14 US_ALU_CONST_G_1 +0x4C18 US_ALU_CONST_B_1 +0x4C1C US_ALU_CONST_A_1 +0x4C20 US_ALU_CONST_R_2 +0x4C24 US_ALU_CONST_G_2 +0x4C28 US_ALU_CONST_B_2 +0x4C2C US_ALU_CONST_A_2 +0x4C30 US_ALU_CONST_R_3 +0x4C34 US_ALU_CONST_G_3 +0x4C38 US_ALU_CONST_B_3 +0x4C3C US_ALU_CONST_A_3 +0x4C40 US_ALU_CONST_R_4 +0x4C44 US_ALU_CONST_G_4 +0x4C48 US_ALU_CONST_B_4 +0x4C4C US_ALU_CONST_A_4 +0x4C50 US_ALU_CONST_R_5 +0x4C54 US_ALU_CONST_G_5 +0x4C58 US_ALU_CONST_B_5 +0x4C5C US_ALU_CONST_A_5 +0x4C60 US_ALU_CONST_R_6 +0x4C64 US_ALU_CONST_G_6 +0x4C68 US_ALU_CONST_B_6 +0x4C6C US_ALU_CONST_A_6 +0x4C70 US_ALU_CONST_R_7 +0x4C74 US_ALU_CONST_G_7 +0x4C78 US_ALU_CONST_B_7 +0x4C7C US_ALU_CONST_A_7 +0x4C80 US_ALU_CONST_R_8 +0x4C84 US_ALU_CONST_G_8 +0x4C88 US_ALU_CONST_B_8 +0x4C8C US_ALU_CONST_A_8 +0x4C90 US_ALU_CONST_R_9 +0x4C94 US_ALU_CONST_G_9 +0x4C98 US_ALU_CONST_B_9 +0x4C9C US_ALU_CONST_A_9 +0x4CA0 US_ALU_CONST_R_10 +0x4CA4 US_ALU_CONST_G_10 +0x4CA8 US_ALU_CONST_B_10 +0x4CAC US_ALU_CONST_A_10 +0x4CB0 US_ALU_CONST_R_11 +0x4CB4 US_ALU_CONST_G_11 +0x4CB8 US_ALU_CONST_B_11 +0x4CBC US_ALU_CONST_A_11 +0x4CC0 US_ALU_CONST_R_12 +0x4CC4 US_ALU_CONST_G_12 +0x4CC8 US_ALU_CONST_B_12 +0x4CCC US_ALU_CONST_A_12 +0x4CD0 US_ALU_CONST_R_13 +0x4CD4 US_ALU_CONST_G_13 +0x4CD8 US_ALU_CONST_B_13 +0x4CDC US_ALU_CONST_A_13 +0x4CE0 US_ALU_CONST_R_14 +0x4CE4 US_ALU_CONST_G_14 +0x4CE8 US_ALU_CONST_B_14 +0x4CEC US_ALU_CONST_A_14 +0x4CF0 US_ALU_CONST_R_15 +0x4CF4 US_ALU_CONST_G_15 +0x4CF8 US_ALU_CONST_B_15 +0x4CFC US_ALU_CONST_A_15 +0x4D00 US_ALU_CONST_R_16 +0x4D04 US_ALU_CONST_G_16 +0x4D08 US_ALU_CONST_B_16 +0x4D0C US_ALU_CONST_A_16 +0x4D10 US_ALU_CONST_R_17 +0x4D14 US_ALU_CONST_G_17 +0x4D18 US_ALU_CONST_B_17 +0x4D1C US_ALU_CONST_A_17 +0x4D20 US_ALU_CONST_R_18 +0x4D24 US_ALU_CONST_G_18 +0x4D28 US_ALU_CONST_B_18 +0x4D2C US_ALU_CONST_A_18 +0x4D30 US_ALU_CONST_R_19 +0x4D34 US_ALU_CONST_G_19 +0x4D38 US_ALU_CONST_B_19 +0x4D3C US_ALU_CONST_A_19 +0x4D40 US_ALU_CONST_R_20 +0x4D44 US_ALU_CONST_G_20 +0x4D48 US_ALU_CONST_B_20 +0x4D4C US_ALU_CONST_A_20 +0x4D50 US_ALU_CONST_R_21 +0x4D54 US_ALU_CONST_G_21 +0x4D58 US_ALU_CONST_B_21 +0x4D5C US_ALU_CONST_A_21 +0x4D60 US_ALU_CONST_R_22 +0x4D64 US_ALU_CONST_G_22 +0x4D68 US_ALU_CONST_B_22 +0x4D6C US_ALU_CONST_A_22 +0x4D70 US_ALU_CONST_R_23 +0x4D74 US_ALU_CONST_G_23 +0x4D78 US_ALU_CONST_B_23 +0x4D7C US_ALU_CONST_A_23 +0x4D80 US_ALU_CONST_R_24 +0x4D84 US_ALU_CONST_G_24 +0x4D88 US_ALU_CONST_B_24 +0x4D8C US_ALU_CONST_A_24 +0x4D90 US_ALU_CONST_R_25 +0x4D94 US_ALU_CONST_G_25 +0x4D98 US_ALU_CONST_B_25 +0x4D9C US_ALU_CONST_A_25 +0x4DA0 US_ALU_CONST_R_26 +0x4DA4 US_ALU_CONST_G_26 +0x4DA8 US_ALU_CONST_B_26 +0x4DAC US_ALU_CONST_A_26 +0x4DB0 US_ALU_CONST_R_27 +0x4DB4 US_ALU_CONST_G_27 +0x4DB8 US_ALU_CONST_B_27 +0x4DBC US_ALU_CONST_A_27 +0x4DC0 US_ALU_CONST_R_28 +0x4DC4 US_ALU_CONST_G_28 +0x4DC8 US_ALU_CONST_B_28 +0x4DCC US_ALU_CONST_A_28 +0x4DD0 US_ALU_CONST_R_29 +0x4DD4 US_ALU_CONST_G_29 +0x4DD8 US_ALU_CONST_B_29 +0x4DDC US_ALU_CONST_A_29 +0x4DE0 US_ALU_CONST_R_30 +0x4DE4 US_ALU_CONST_G_30 +0x4DE8 US_ALU_CONST_B_30 +0x4DEC US_ALU_CONST_A_30 +0x4DF0 US_ALU_CONST_R_31 +0x4DF4 US_ALU_CONST_G_31 +0x4DF8 US_ALU_CONST_B_31 +0x4DFC US_ALU_CONST_A_31 +0x4E04 RB3D_BLENDCNTL_R3 +0x4E08 RB3D_ABLENDCNTL_R3 +0x4E0C RB3D_COLOR_CHANNEL_MASK +0x4E10 RB3D_CONSTANT_COLOR +0x4E14 RB3D_COLOR_CLEAR_VALUE +0x4E18 RB3D_ROPCNTL_R3 +0x4E1C RB3D_CLRCMP_FLIPE_R3 +0x4E20 RB3D_CLRCMP_CLR_R3 +0x4E24 RB3D_CLRCMP_MSK_R3 +0x4E48 RB3D_DEBUG_CTL +0x4E4C RB3D_DSTCACHE_CTLSTAT_R3 +0x4E50 RB3D_DITHER_CTL +0x4E54 RB3D_CMASK_OFFSET0 +0x4E58 RB3D_CMASK_OFFSET1 +0x4E5C RB3D_CMASK_OFFSET2 +0x4E60 RB3D_CMASK_OFFSET3 +0x4E64 RB3D_CMASK_PITCH0 +0x4E68 RB3D_CMASK_PITCH1 +0x4E6C RB3D_CMASK_PITCH2 +0x4E70 RB3D_CMASK_PITCH3 +0x4E74 RB3D_CMASK_WRINDEX +0x4E78 RB3D_CMASK_DWORD +0x4E7C RB3D_CMASK_RDINDEX +0x4E80 RB3D_AARESOLVE_OFFSET +0x4E84 RB3D_AARESOLVE_PITCH +0x4E88 RB3D_AARESOLVE_CTL +0x4EA0 RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD +0x4EA4 RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD +0x4F04 ZB_ZSTENCILCNTL +0x4F08 ZB_STENCILREFMASK +0x4F14 ZB_ZTOP +0x4F18 ZB_ZCACHE_CTLSTAT +0x4F1C ZB_BW_CNTL +0x4F28 ZB_DEPTHCLEARVALUE +0x4F30 ZB_ZMASK_OFFSET +0x4F34 ZB_ZMASK_PITCH +0x4F38 ZB_ZMASK_WRINDEX +0x4F3C ZB_ZMASK_DWORD +0x4F40 ZB_ZMASK_RDINDEX +0x4F44 ZB_HIZ_OFFSET +0x4F48 ZB_HIZ_WRINDEX +0x4F4C ZB_HIZ_DWORD +0x4F50 ZB_HIZ_RDINDEX +0x4F54 ZB_HIZ_PITCH +0x4F58 ZB_ZPASS_DATA diff --git a/drivers/gpu/drm/radeon/reg_srcs/rs600 b/drivers/gpu/drm/radeon/reg_srcs/rs600 index 8e3c0b807ad..6801b865d1c 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rs600 +++ b/drivers/gpu/drm/radeon/reg_srcs/rs600 @@ -153,7 +153,7 @@ rs600 0x6d40 0x42A4 SU_POLY_OFFSET_FRONT_SCALE 0x42A8 SU_POLY_OFFSET_FRONT_OFFSET 0x42AC SU_POLY_OFFSET_BACK_SCALE -0x42B0 SU_POLY_OFFSET_BACK_OFFSET +0x42B0 SU_POLY_OFFSET_BACK_OFFSET 0x42B4 SU_POLY_OFFSET_ENABLE 0x42B8 SU_CULL_MODE 0x42C0 SU_DEPTH_SCALE @@ -291,6 +291,8 @@ rs600 0x6d40 0x46AC US_OUT_FMT_2 0x46B0 US_OUT_FMT_3 0x46B4 US_W_FMT +0x46B8 US_CODE_BANK +0x46BC US_CODE_EXT 0x46C0 US_ALU_RGB_ADDR_0 0x46C4 US_ALU_RGB_ADDR_1 0x46C8 US_ALU_RGB_ADDR_2 @@ -547,6 +549,70 @@ rs600 0x6d40 0x4AB4 US_ALU_ALPHA_INST_61 0x4AB8 US_ALU_ALPHA_INST_62 0x4ABC US_ALU_ALPHA_INST_63 +0x4AC0 US_ALU_EXT_ADDR_0 +0x4AC4 US_ALU_EXT_ADDR_1 +0x4AC8 US_ALU_EXT_ADDR_2 +0x4ACC US_ALU_EXT_ADDR_3 +0x4AD0 US_ALU_EXT_ADDR_4 +0x4AD4 US_ALU_EXT_ADDR_5 +0x4AD8 US_ALU_EXT_ADDR_6 +0x4ADC US_ALU_EXT_ADDR_7 +0x4AE0 US_ALU_EXT_ADDR_8 +0x4AE4 US_ALU_EXT_ADDR_9 +0x4AE8 US_ALU_EXT_ADDR_10 +0x4AEC US_ALU_EXT_ADDR_11 +0x4AF0 US_ALU_EXT_ADDR_12 +0x4AF4 US_ALU_EXT_ADDR_13 +0x4AF8 US_ALU_EXT_ADDR_14 +0x4AFC US_ALU_EXT_ADDR_15 +0x4B00 US_ALU_EXT_ADDR_16 +0x4B04 US_ALU_EXT_ADDR_17 +0x4B08 US_ALU_EXT_ADDR_18 +0x4B0C US_ALU_EXT_ADDR_19 +0x4B10 US_ALU_EXT_ADDR_20 +0x4B14 US_ALU_EXT_ADDR_21 +0x4B18 US_ALU_EXT_ADDR_22 +0x4B1C US_ALU_EXT_ADDR_23 +0x4B20 US_ALU_EXT_ADDR_24 +0x4B24 US_ALU_EXT_ADDR_25 +0x4B28 US_ALU_EXT_ADDR_26 +0x4B2C US_ALU_EXT_ADDR_27 +0x4B30 US_ALU_EXT_ADDR_28 +0x4B34 US_ALU_EXT_ADDR_29 +0x4B38 US_ALU_EXT_ADDR_30 +0x4B3C US_ALU_EXT_ADDR_31 +0x4B40 US_ALU_EXT_ADDR_32 +0x4B44 US_ALU_EXT_ADDR_33 +0x4B48 US_ALU_EXT_ADDR_34 +0x4B4C US_ALU_EXT_ADDR_35 +0x4B50 US_ALU_EXT_ADDR_36 +0x4B54 US_ALU_EXT_ADDR_37 +0x4B58 US_ALU_EXT_ADDR_38 +0x4B5C US_ALU_EXT_ADDR_39 +0x4B60 US_ALU_EXT_ADDR_40 +0x4B64 US_ALU_EXT_ADDR_41 +0x4B68 US_ALU_EXT_ADDR_42 +0x4B6C US_ALU_EXT_ADDR_43 +0x4B70 US_ALU_EXT_ADDR_44 +0x4B74 US_ALU_EXT_ADDR_45 +0x4B78 US_ALU_EXT_ADDR_46 +0x4B7C US_ALU_EXT_ADDR_47 +0x4B80 US_ALU_EXT_ADDR_48 +0x4B84 US_ALU_EXT_ADDR_49 +0x4B88 US_ALU_EXT_ADDR_50 +0x4B8C US_ALU_EXT_ADDR_51 +0x4B90 US_ALU_EXT_ADDR_52 +0x4B94 US_ALU_EXT_ADDR_53 +0x4B98 US_ALU_EXT_ADDR_54 +0x4B9C US_ALU_EXT_ADDR_55 +0x4BA0 US_ALU_EXT_ADDR_56 +0x4BA4 US_ALU_EXT_ADDR_57 +0x4BA8 US_ALU_EXT_ADDR_58 +0x4BAC US_ALU_EXT_ADDR_59 +0x4BB0 US_ALU_EXT_ADDR_60 +0x4BB4 US_ALU_EXT_ADDR_61 +0x4BB8 US_ALU_EXT_ADDR_62 +0x4BBC US_ALU_EXT_ADDR_63 0x4BC0 FG_FOG_BLEND 0x4BC4 FG_FOG_FACTOR 0x4BC8 FG_FOG_COLOR_R diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 0102a0d5735..38abf63bf2c 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 @@ -161,7 +161,12 @@ rv515 0x6d40 0x401C GB_SELECT 0x4020 GB_AA_CONFIG 0x4024 GB_FIFO_SIZE +0x4028 GB_Z_PEQ_CONFIG 0x4100 TX_INVALTAGS +0x4114 SU_TEX_WRAP_PS3 +0x4118 PS3_ENABLE +0x411c PS3_VTX_FMT +0x4120 PS3_TEX_SOURCE 0x4200 GA_POINT_S0 0x4204 GA_POINT_T0 0x4208 GA_POINT_S1 @@ -171,6 +176,7 @@ rv515 0x6d40 0x4230 GA_POINT_MINMAX 0x4234 GA_LINE_CNTL 0x4238 GA_LINE_STIPPLE_CONFIG +0x4258 GA_COLOR_CONTROL_PS3 0x4260 GA_LINE_STIPPLE_VALUE 0x4264 GA_LINE_S0 0x4268 GA_LINE_S1 -- cgit v1.2.3 From 89347bb8ef2d0af1ae8d847b7df91e9f04eccf2a Mon Sep 17 00:00:00 2001 From: David John Date: Thu, 31 Dec 2009 12:00:46 +0530 Subject: drm: Keep disabled outputs disabled after suspend / resume With the current DRM code, an output that has been powered off from userspace will automatically power back on when resuming from suspend. This patch fixes this behaviour. Tested only with the Intel i915 driver on an Intel GM45 Express chipset. Signed-off-by: David John Reviewed-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 4231d6db72e..aba79c49458 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -216,7 +216,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc) EXPORT_SYMBOL(drm_helper_crtc_in_use); /** - * drm_disable_unused_functions - disable unused objects + * drm_helper_disable_unused_functions - disable unused objects * @dev: DRM device * * LOCKING: @@ -1162,6 +1162,9 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); int drm_helper_resume_force_mode(struct drm_device *dev) { struct drm_crtc *crtc; + struct drm_encoder *encoder; + struct drm_encoder_helper_funcs *encoder_funcs; + struct drm_crtc_helper_funcs *crtc_funcs; int ret; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -1174,6 +1177,25 @@ int drm_helper_resume_force_mode(struct drm_device *dev) if (ret == false) DRM_ERROR("failed to set mode on crtc %p\n", crtc); + + /* Turn off outputs that were already powered off */ + if (drm_helper_choose_crtc_dpms(crtc)) { + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + + if(encoder->crtc != crtc) + continue; + + encoder_funcs = encoder->helper_private; + if (encoder_funcs->dpms) + (*encoder_funcs->dpms) (encoder, + drm_helper_choose_encoder_dpms(encoder)); + + crtc_funcs = crtc->helper_private; + if (crtc_funcs->dpms) + (*crtc_funcs->dpms) (crtc, + drm_helper_choose_crtc_dpms(crtc)); + } + } } /* disable the unused connectors while restoring the modesetting */ drm_helper_disable_unused_functions(dev); -- cgit v1.2.3 From 509c7d83c3b18a50a0bd02afa43c8ee3c7605bc9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 8 Jan 2010 09:27:08 +1000 Subject: drm/kms/fb: check for depth changes from userspace for resizing. If userspace (plymouth in this case) asks for a deeper depth, refuse it as well due to lack of resizing. This fixes an issue since < 32MB cards went to 8bpp and plymouth crashes on startup. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 100ee48760b..1c2b7d44ec0 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -606,11 +606,10 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, return -EINVAL; /* Need to resize the fb object !!! */ - if (var->xres > fb->width || var->yres > fb->height) { - DRM_ERROR("Requested width/height is greater than current fb " - "object %dx%d > %dx%d\n", var->xres, var->yres, - fb->width, fb->height); - DRM_ERROR("Need resizing code.\n"); + if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) { + DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb " + "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel, + fb->width, fb->height, fb->bits_per_pixel); return -EINVAL; } -- cgit v1.2.3 From 94fd163d86b049842856864cdeac318131ec576d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 11 Jan 2010 14:20:55 +1000 Subject: drm: reduce WARN_ON to a printk. Lots of ppl keep thinking this is an oops, it was just a warning for me to see, just make it a printk now. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index aba79c49458..077313f0d47 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1032,7 +1032,7 @@ bool drm_helper_initial_config(struct drm_device *dev) /* * we shouldn't end up with no modes here. */ - WARN(!count, "No connectors reported connected with modes\n"); + printk(KERN_INFO "No connectors reported conncted with modes\n"); drm_setup_crtcs(dev); -- cgit v1.2.3 From 617e234b01757698ed5f8c9a5fbf12717b76e371 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 13 Dec 2009 20:07:42 +0100 Subject: drm/nouveau: Add cache_flush/pull fifo engine functions. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_drv.h | 4 ++++ drivers/gpu/drm/nouveau/nouveau_state.c | 10 ++++++++++ drivers/gpu/drm/nouveau/nv04_fifo.c | 34 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 5f8cbb79c49..48d0ad9434a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -292,6 +292,8 @@ struct nouveau_fifo_engine { void (*disable)(struct drm_device *); void (*enable)(struct drm_device *); bool (*reassign)(struct drm_device *, bool enable); + bool (*cache_flush)(struct drm_device *dev); + bool (*cache_pull)(struct drm_device *dev, bool enable); int (*channel_id)(struct drm_device *); @@ -889,6 +891,8 @@ extern int nv04_fifo_init(struct drm_device *); extern void nv04_fifo_disable(struct drm_device *); extern void nv04_fifo_enable(struct drm_device *); extern bool nv04_fifo_reassign(struct drm_device *, bool); +extern bool nv04_fifo_cache_flush(struct drm_device *); +extern bool nv04_fifo_cache_pull(struct drm_device *, bool); extern int nv04_fifo_channel_id(struct drm_device *); extern int nv04_fifo_create_context(struct nouveau_channel *); extern void nv04_fifo_destroy_context(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index e76ec2d207a..9f988431f34 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -76,6 +76,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv04_fifo_channel_id; engine->fifo.create_context = nv04_fifo_create_context; engine->fifo.destroy_context = nv04_fifo_destroy_context; @@ -115,6 +117,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; @@ -154,6 +158,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; @@ -193,6 +199,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; engine->fifo.destroy_context = nv10_fifo_destroy_context; @@ -233,6 +241,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; + engine->fifo.cache_flush = nv04_fifo_cache_flush; + engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv40_fifo_create_context; engine->fifo.destroy_context = nv40_fifo_destroy_context; diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index 0c3cd53c731..f31347b8c9b 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c @@ -71,6 +71,40 @@ nv04_fifo_reassign(struct drm_device *dev, bool enable) return (reassign == 1); } +bool +nv04_fifo_cache_flush(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + uint64_t start = ptimer->read(dev); + + do { + if (nv_rd32(dev, NV03_PFIFO_CACHE1_GET) == + nv_rd32(dev, NV03_PFIFO_CACHE1_PUT)) + return true; + + } while (ptimer->read(dev) - start < 100000000); + + NV_ERROR(dev, "Timeout flushing the PFIFO cache.\n"); + + return false; +} + +bool +nv04_fifo_cache_pull(struct drm_device *dev, bool enable) +{ + uint32_t pull = nv_rd32(dev, NV04_PFIFO_CACHE1_PULL0); + + if (enable) { + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull | 1); + } else { + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, pull & ~1); + nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + } + + return !!(pull & 1); +} + int nv04_fifo_channel_id(struct drm_device *dev) { -- cgit v1.2.3 From 0d87c100312ce75d9bb75a456d8a542e84a1722f Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 12:12:27 +0100 Subject: drm/nouveau: Pre-G80 tiling support. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_drv.h | 18 +++++ drivers/gpu/drm/nouveau/nouveau_reg.h | 16 ++--- drivers/gpu/drm/nouveau/nouveau_state.c | 8 +++ drivers/gpu/drm/nouveau/nv10_fb.c | 32 +++++++-- drivers/gpu/drm/nouveau/nv10_graph.c | 28 +++++--- drivers/gpu/drm/nouveau/nv20_graph.c | 61 ++++++++--------- drivers/gpu/drm/nouveau/nv40_fb.c | 53 +++++++++------ drivers/gpu/drm/nouveau/nv40_graph.c | 116 +++++++++++++------------------- 8 files changed, 185 insertions(+), 147 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 48d0ad9434a..446a92ad2ee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -277,8 +277,13 @@ struct nouveau_timer_engine { }; struct nouveau_fb_engine { + int num_tiles; + int (*init)(struct drm_device *dev); void (*takedown)(struct drm_device *dev); + + void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch); }; struct nouveau_fifo_engine { @@ -332,6 +337,9 @@ struct nouveau_pgraph_engine { void (*destroy_context)(struct nouveau_channel *); int (*load_context)(struct nouveau_channel *); int (*unload_context)(struct drm_device *); + + void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch); }; struct nouveau_engine { @@ -881,10 +889,14 @@ extern void nv04_fb_takedown(struct drm_device *); /* nv10_fb.c */ extern int nv10_fb_init(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *); +extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv40_fb.c */ extern int nv40_fb_init(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *); +extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv04_fifo.c */ extern int nv04_fifo_init(struct drm_device *); @@ -945,6 +957,8 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *); extern int nv10_graph_load_context(struct nouveau_channel *); extern int nv10_graph_unload_context(struct drm_device *); extern void nv10_graph_context_switch(struct drm_device *); +extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv20_graph.c */ extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; @@ -956,6 +970,8 @@ extern int nv20_graph_unload_context(struct drm_device *); extern int nv20_graph_init(struct drm_device *); extern void nv20_graph_takedown(struct drm_device *); extern int nv30_graph_init(struct drm_device *); +extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv40_graph.c */ extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; @@ -967,6 +983,8 @@ extern void nv40_graph_destroy_context(struct nouveau_channel *); extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); extern void nv40_grctx_init(struct nouveau_grctx *); +extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t, + uint32_t, uint32_t); /* nv50_graph.c */ extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index fa1b0e7165b..251f1b3b38b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h @@ -349,19 +349,19 @@ #define NV04_PGRAPH_BLEND 0x00400824 #define NV04_PGRAPH_STORED_FMT 0x00400830 #define NV04_PGRAPH_PATT_COLORRAM 0x00400900 -#define NV40_PGRAPH_TILE0(i) (0x00400900 + (i*16)) -#define NV40_PGRAPH_TLIMIT0(i) (0x00400904 + (i*16)) -#define NV40_PGRAPH_TSIZE0(i) (0x00400908 + (i*16)) -#define NV40_PGRAPH_TSTATUS0(i) (0x0040090C + (i*16)) +#define NV20_PGRAPH_TILE(i) (0x00400900 + (i*16)) +#define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) +#define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) +#define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) #define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) #define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) #define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) #define NV10_PGRAPH_TSTATUS(i) (0x00400B0C + (i*16)) #define NV04_PGRAPH_U_RAM 0x00400D00 -#define NV47_PGRAPH_TILE0(i) (0x00400D00 + (i*16)) -#define NV47_PGRAPH_TLIMIT0(i) (0x00400D04 + (i*16)) -#define NV47_PGRAPH_TSIZE0(i) (0x00400D08 + (i*16)) -#define NV47_PGRAPH_TSTATUS0(i) (0x00400D0C + (i*16)) +#define NV47_PGRAPH_TILE(i) (0x00400D00 + (i*16)) +#define NV47_PGRAPH_TLIMIT(i) (0x00400D04 + (i*16)) +#define NV47_PGRAPH_TSIZE(i) (0x00400D08 + (i*16)) +#define NV47_PGRAPH_TSTATUS(i) (0x00400D0C + (i*16)) #define NV04_PGRAPH_V_RAM 0x00400D40 #define NV04_PGRAPH_W_RAM 0x00400D80 #define NV10_PGRAPH_COMBINER0_IN_ALPHA 0x00400E40 diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 9f988431f34..6a459139910 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -102,6 +102,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; engine->graph.grclass = nv10_graph_grclass; engine->graph.init = nv10_graph_init; engine->graph.takedown = nv10_graph_takedown; @@ -111,6 +112,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.load_context = nv10_graph_load_context; engine->graph.unload_context = nv10_graph_unload_context; + engine->graph.set_region_tiling = nv10_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; @@ -143,6 +145,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; engine->graph.grclass = nv20_graph_grclass; engine->graph.init = nv20_graph_init; engine->graph.takedown = nv20_graph_takedown; @@ -152,6 +155,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.load_context = nv20_graph_load_context; engine->graph.unload_context = nv20_graph_unload_context; + engine->graph.set_region_tiling = nv20_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; @@ -184,6 +188,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; + engine->fb.set_region_tiling = nv10_fb_set_region_tiling; engine->graph.grclass = nv30_graph_grclass; engine->graph.init = nv30_graph_init; engine->graph.takedown = nv20_graph_takedown; @@ -193,6 +198,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv20_graph_destroy_context; engine->graph.load_context = nv20_graph_load_context; engine->graph.unload_context = nv20_graph_unload_context; + engine->graph.set_region_tiling = nv20_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; @@ -226,6 +232,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv40_fb_init; engine->fb.takedown = nv40_fb_takedown; + engine->fb.set_region_tiling = nv40_fb_set_region_tiling; engine->graph.grclass = nv40_graph_grclass; engine->graph.init = nv40_graph_init; engine->graph.takedown = nv40_graph_takedown; @@ -235,6 +242,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.unload_context = nv40_graph_unload_context; + engine->graph.set_region_tiling = nv40_graph_set_region_tiling; engine->fifo.channels = 32; engine->fifo.init = nv40_fifo_init; engine->fifo.takedown = nouveau_stub_takedown; diff --git a/drivers/gpu/drm/nouveau/nv10_fb.c b/drivers/gpu/drm/nouveau/nv10_fb.c index 79e2d104d70..cc5cda44e50 100644 --- a/drivers/gpu/drm/nouveau/nv10_fb.c +++ b/drivers/gpu/drm/nouveau/nv10_fb.c @@ -3,17 +3,37 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +void +nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) { + if (dev_priv->card_type >= NV_20) + addr |= 1; + else + addr |= 1 << 31; + } + + nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); + nv_wr32(dev, NV10_PFB_TILE(i), addr); +} + int nv10_fb_init(struct drm_device *dev) { - uint32_t fb_bar_size; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; int i; - fb_bar_size = drm_get_resource_len(dev, 0) - 1; - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, NV10_PFB_TILE(i), 0); - nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); - } + pfb->num_tiles = NV10_PFB_TILE__SIZE; + + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_region_tiling(dev, i, 0, 0, 0); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index 6870e0ee2e7..fcf2cdd1949 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c @@ -807,6 +807,20 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan) chan->pgraph_ctx = NULL; } +void +nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1 << 31; + + nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV10_PGRAPH_TILE(i), addr); +} + int nv10_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -838,17 +852,9 @@ int nv10_graph_init(struct drm_device *dev) } else nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); - /* copy tile info from PFB */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, NV10_PGRAPH_TILE(i), - nv_rd32(dev, NV10_PFB_TILE(i))); - nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - nv_wr32(dev, NV10_PGRAPH_TSIZE(i), - nv_rd32(dev, NV10_PFB_TSIZE(i))); - nv_wr32(dev, NV10_PGRAPH_TSTATUS(i), - nv_rd32(dev, NV10_PFB_TSTATUS(i))); - } + /* Turn all the tiling regions off. */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) + nv10_graph_set_region_tiling(dev, i, 0, 0, 0); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index 18ba74f1970..d6fc0a82f03 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c @@ -514,6 +514,27 @@ nv20_graph_rdi(struct drm_device *dev) nouveau_wait_for_idle(dev); } +void +nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1; + + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr); +} + int nv20_graph_init(struct drm_device *dev) { @@ -572,27 +593,10 @@ nv20_graph_init(struct drm_device *dev) nv_wr32(dev, NV10_PGRAPH_RDI_DATA , 0x00000030); } - /* copy tile info from PFB */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, 0x00400904 + i * 0x10, - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - nv_wr32(dev, 0x00400908 + i * 0x10, - nv_rd32(dev, NV10_PFB_TSIZE(i))); - /* which is NV40_PGRAPH_TSIZE0(i) ?? */ - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, NV10_PFB_TSIZE(i))); - nv_wr32(dev, 0x00400900 + i * 0x10, - nv_rd32(dev, NV10_PFB_TILE(i))); - /* which is NV40_PGRAPH_TILE0(i) ?? */ - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, NV10_PFB_TILE(i))); - } + /* Turn all the tiling regions off. */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) + nv20_graph_set_region_tiling(dev, i, 0, 0, 0); + for (i = 0; i < 8; i++) { nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); @@ -704,18 +708,9 @@ nv30_graph_init(struct drm_device *dev) nv_wr32(dev, 0x4000c0, 0x00000016); - /* copy tile info from PFB */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - nv_wr32(dev, 0x00400904 + i * 0x10, - nv_rd32(dev, NV10_PFB_TLIMIT(i))); - /* which is NV40_PGRAPH_TLIMIT0(i) ?? */ - nv_wr32(dev, 0x00400908 + i * 0x10, - nv_rd32(dev, NV10_PFB_TSIZE(i))); - /* which is NV40_PGRAPH_TSIZE0(i) ?? */ - nv_wr32(dev, 0x00400900 + i * 0x10, - nv_rd32(dev, NV10_PFB_TILE(i))); - /* which is NV40_PGRAPH_TILE0(i) ?? */ - } + /* Turn all the tiling regions off. */ + for (i = 0; i < NV10_PFB_TILE__SIZE; i++) + nv20_graph_set_region_tiling(dev, i, 0, 0, 0); nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c index ca1d27107a8..3cd07d8d5bd 100644 --- a/drivers/gpu/drm/nouveau/nv40_fb.c +++ b/drivers/gpu/drm/nouveau/nv40_fb.c @@ -3,12 +3,37 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +void +nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1; + + switch (dev_priv->chipset) { + case 0x40: + nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); + nv_wr32(dev, NV10_PFB_TILE(i), addr); + break; + + default: + nv_wr32(dev, NV40_PFB_TLIMIT(i), limit); + nv_wr32(dev, NV40_PFB_TSIZE(i), pitch); + nv_wr32(dev, NV40_PFB_TILE(i), addr); + break; + } +} + int nv40_fb_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t fb_bar_size, tmp; - int num_tiles; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + uint32_t tmp; int i; /* This is strictly a NV4x register (don't know about NV5x). */ @@ -23,35 +48,23 @@ nv40_fb_init(struct drm_device *dev) case 0x45: tmp = nv_rd32(dev, NV10_PFB_CLOSE_PAGE2); nv_wr32(dev, NV10_PFB_CLOSE_PAGE2, tmp & ~(1 << 15)); - num_tiles = NV10_PFB_TILE__SIZE; + pfb->num_tiles = NV10_PFB_TILE__SIZE; break; case 0x46: /* G72 */ case 0x47: /* G70 */ case 0x49: /* G71 */ case 0x4b: /* G73 */ case 0x4c: /* C51 (G7X version) */ - num_tiles = NV40_PFB_TILE__SIZE_1; + pfb->num_tiles = NV40_PFB_TILE__SIZE_1; break; default: - num_tiles = NV40_PFB_TILE__SIZE_0; + pfb->num_tiles = NV40_PFB_TILE__SIZE_0; break; } - fb_bar_size = drm_get_resource_len(dev, 0) - 1; - switch (dev_priv->chipset) { - case 0x40: - for (i = 0; i < num_tiles; i++) { - nv_wr32(dev, NV10_PFB_TILE(i), 0); - nv_wr32(dev, NV10_PFB_TLIMIT(i), fb_bar_size); - } - break; - default: - for (i = 0; i < num_tiles; i++) { - nv_wr32(dev, NV40_PFB_TILE(i), 0); - nv_wr32(dev, NV40_PFB_TLIMIT(i), fb_bar_size); - } - break; - } + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + pfb->set_region_tiling(dev, i, 0, 0, 0); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 2b332bb55ac..53e8afe1dcd 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -181,6 +181,48 @@ nv40_graph_unload_context(struct drm_device *dev) return ret; } +void +nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t limit = max(1u, addr + size) - 1; + + if (pitch) + addr |= 1; + + switch (dev_priv->chipset) { + case 0x44: + case 0x4a: + case 0x4e: + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + break; + + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV47_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); + break; + + default: + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); + break; + } +} + /* * G70 0x47 * G71 0x49 @@ -195,7 +237,8 @@ nv40_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = (struct drm_nouveau_private *)dev->dev_private; - uint32_t vramsz, tmp; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + uint32_t vramsz; int i, j; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & @@ -292,74 +335,9 @@ nv40_graph_init(struct drm_device *dev) nv_wr32(dev, 0x400b38, 0x2ffff800); nv_wr32(dev, 0x400b3c, 0x00006000); - /* copy tile info from PFB */ - switch (dev_priv->chipset) { - case 0x40: /* vanilla NV40 */ - for (i = 0; i < NV10_PFB_TILE__SIZE; i++) { - tmp = nv_rd32(dev, NV10_PFB_TILE(i)); - nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); - tmp = nv_rd32(dev, NV10_PFB_TLIMIT(i)); - nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); - tmp = nv_rd32(dev, NV10_PFB_TSIZE(i)); - nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); - tmp = nv_rd32(dev, NV10_PFB_TSTATUS(i)); - nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); - } - break; - case 0x44: - case 0x4a: - case 0x4e: /* NV44-based cores don't have 0x406900? */ - for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) { - tmp = nv_rd32(dev, NV40_PFB_TILE(i)); - nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); - nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); - nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); - nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); - } - break; - case 0x46: - case 0x47: - case 0x49: - case 0x4b: /* G7X-based cores */ - for (i = 0; i < NV40_PFB_TILE__SIZE_1; i++) { - tmp = nv_rd32(dev, NV40_PFB_TILE(i)); - nv_wr32(dev, NV47_PGRAPH_TILE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); - nv_wr32(dev, NV47_PGRAPH_TLIMIT0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); - nv_wr32(dev, NV47_PGRAPH_TSIZE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); - nv_wr32(dev, NV47_PGRAPH_TSTATUS0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); - } - break; - default: /* everything else */ - for (i = 0; i < NV40_PFB_TILE__SIZE_0; i++) { - tmp = nv_rd32(dev, NV40_PFB_TILE(i)); - nv_wr32(dev, NV40_PGRAPH_TILE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TLIMIT(i)); - nv_wr32(dev, NV40_PGRAPH_TLIMIT0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSIZE(i)); - nv_wr32(dev, NV40_PGRAPH_TSIZE0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tmp); - tmp = nv_rd32(dev, NV40_PFB_TSTATUS(i)); - nv_wr32(dev, NV40_PGRAPH_TSTATUS0(i), tmp); - nv_wr32(dev, NV40_PGRAPH_TSTATUS1(i), tmp); - } - break; - } + /* Turn all the tiling regions off. */ + for (i = 0; i < pfb->num_tiles; i++) + nv40_graph_set_region_tiling(dev, i, 0, 0, 0); /* begin RAM config */ vramsz = drm_get_resource_len(dev, 0) - 1; -- cgit v1.2.3 From 287c1532145b63d394060d46c0309b123b862345 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 11 Dec 2009 16:51:09 +0100 Subject: drm/nouveau: Make the MM aware of pre-G80 tiling. This commit has also the following 3 bugfix commits squashed into it from the nouveau git tree: drm/nouveau: Fix up the tiling alignment restrictions for nv1x. drm/nouveau: Fix up the nv2x tiling alignment restrictions. drm/nv50: fix align typo for g9x Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 221 ++++++++++++++++++++++++---------- drivers/gpu/drm/nouveau/nouveau_drv.h | 22 ++++ drivers/gpu/drm/nouveau/nouveau_mem.c | 87 +++++++++++++ 3 files changed, 265 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 0cad6d834eb..1d6036fabd5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -37,6 +37,7 @@ static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); ttm_bo_kunmap(&nvbo->kmap); @@ -44,12 +45,83 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) if (unlikely(nvbo->gem)) DRM_ERROR("bo %p still attached to GEM object\n", bo); + if (nvbo->tile) + nv10_mem_expire_tiling(dev, nvbo->tile, NULL); + spin_lock(&dev_priv->ttm.bo_list_lock); list_del(&nvbo->head); spin_unlock(&dev_priv->ttm.bo_list_lock); kfree(nvbo); } +static void +nouveau_bo_fixup_align(struct drm_device *dev, + uint32_t tile_mode, uint32_t tile_flags, + int *align, int *size) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* + * Some of the tile_flags have a periodic structure of N*4096 bytes, + * align to to that as well as the page size. Overallocate memory to + * avoid corruption of other buffer objects. + */ + if (dev_priv->card_type == NV_50) { + switch (tile_flags) { + case 0x1800: + case 0x2800: + case 0x4800: + case 0x7a00: + if (dev_priv->chipset >= 0xA0) { + /* This is based on high end cards with 448 bits + * memory bus, could be different elsewhere.*/ + *size += 6 * 28672; + /* 8 * 28672 is the actual alignment requirement + * but we must also align to page size. */ + *align = 2 * 8 * 28672; + } else if (dev_priv->chipset >= 0x90) { + *size += 3 * 16384; + *align = 12 * 16384; + } else { + *size += 3 * 8192; + /* 12 * 8192 is the actual alignment requirement + * but we must also align to page size. */ + *align = 2 * 12 * 8192; + } + break; + default: + break; + } + + } else { + if (tile_mode) { + if (dev_priv->chipset >= 0x40) { + *align = 65536; + *size = roundup(*size, 64 * tile_mode); + + } else if (dev_priv->chipset >= 0x30) { + *align = 32768; + *size = roundup(*size, 64 * tile_mode); + + } else if (dev_priv->chipset >= 0x20) { + *align = 16384; + *size = roundup(*size, 64 * tile_mode); + + } else if (dev_priv->chipset >= 0x10) { + *align = 16384; + *size = roundup(*size, 32 * tile_mode); + } + } + } + + *size = ALIGN(*size, PAGE_SIZE); + + if (dev_priv->card_type == NV_50) { + *size = ALIGN(*size, 65536); + *align = max(65536, *align); + } +} + int nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, int size, int align, uint32_t flags, uint32_t tile_mode, @@ -70,46 +142,9 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, nvbo->tile_mode = tile_mode; nvbo->tile_flags = tile_flags; - /* - * Some of the tile_flags have a periodic structure of N*4096 bytes, - * align to to that as well as the page size. Overallocate memory to - * avoid corruption of other buffer objects. - */ - switch (tile_flags) { - case 0x1800: - case 0x2800: - case 0x4800: - case 0x7a00: - if (dev_priv->chipset >= 0xA0) { - /* This is based on high end cards with 448 bits - * memory bus, could be different elsewhere.*/ - size += 6 * 28672; - /* 8 * 28672 is the actual alignment requirement, - * but we must also align to page size. */ - align = 2 * 8 * 28672; - } else if (dev_priv->chipset >= 0x90) { - size += 3 * 16384; - align = 12 * 16834; - } else { - size += 3 * 8192; - /* 12 * 8192 is the actual alignment requirement, - * but we must also align to page size. */ - align = 2 * 12 * 8192; - } - break; - default: - break; - } - + nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); align >>= PAGE_SHIFT; - size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); - if (dev_priv->card_type == NV_50) { - size = (size + 65535) & ~65535; - if (align < (65536 / PAGE_SIZE)) - align = (65536 / PAGE_SIZE); - } - if (flags & TTM_PL_FLAG_VRAM) nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING; if (flags & TTM_PL_FLAG_TT) @@ -421,6 +456,7 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) /* GPU-assisted copy using NV_MEMORY_TO_MEMORY_FORMAT, can access * TTM_PL_{VRAM,TT} directly. */ + static int nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, struct nouveau_bo *nvbo, bool evict, bool no_wait, @@ -455,11 +491,12 @@ nouveau_bo_mem_ctxdma(struct nouveau_bo *nvbo, struct nouveau_channel *chan, } static int -nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait, - struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) +nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr, + int no_wait, struct ttm_mem_reg *new_mem) { struct nouveau_bo *nvbo = nouveau_bo(bo); struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct ttm_mem_reg *old_mem = &bo->mem; struct nouveau_channel *chan; uint64_t src_offset, dst_offset; uint32_t page_count; @@ -559,7 +596,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, &tmp_mem); + ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, &tmp_mem); if (ret) goto out; @@ -597,7 +634,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = nouveau_bo_move_m2mf(bo, true, no_wait, &bo->mem, new_mem); + ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, new_mem); if (ret) goto out; @@ -612,52 +649,106 @@ out: } static int -nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, - bool no_wait, struct ttm_mem_reg *new_mem) +nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, + struct nouveau_tile_reg **new_tile) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); - struct nouveau_bo *nvbo = nouveau_bo(bo); struct drm_device *dev = dev_priv->dev; - struct ttm_mem_reg *old_mem = &bo->mem; + struct nouveau_bo *nvbo = nouveau_bo(bo); + uint64_t offset; int ret; - if (dev_priv->card_type == NV_50 && new_mem->mem_type == TTM_PL_VRAM && - !nvbo->no_vm) { - uint64_t offset = new_mem->mm_node->start << PAGE_SHIFT; + if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { + /* Nothing to do. */ + *new_tile = NULL; + return 0; + } + + offset = new_mem->mm_node->start << PAGE_SHIFT; + if (dev_priv->card_type == NV_50) { ret = nv50_mem_vm_bind_linear(dev, offset + dev_priv->vm_vram_base, new_mem->size, nvbo->tile_flags, offset); if (ret) return ret; + + } else if (dev_priv->card_type >= NV_10) { + *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, + nvbo->tile_mode); } + return 0; +} + +static void +nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, + struct nouveau_tile_reg *new_tile, + struct nouveau_tile_reg **old_tile) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct drm_device *dev = dev_priv->dev; + + if (dev_priv->card_type >= NV_10 && + dev_priv->card_type < NV_50) { + if (*old_tile) + nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj); + + *old_tile = new_tile; + } +} + +static int +nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, + bool no_wait, struct ttm_mem_reg *new_mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct ttm_mem_reg *old_mem = &bo->mem; + struct nouveau_tile_reg *new_tile = NULL; + int ret = 0; + + ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile); + if (ret) + return ret; + + /* Software copy if the card isn't up and running yet. */ if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || - !dev_priv->channel) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + !dev_priv->channel) { + ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + goto out; + } + /* Fake bo copy. */ if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { BUG_ON(bo->mem.mm_node != NULL); bo->mem = *new_mem; new_mem->mm_node = NULL; - return 0; + goto out; } - if (new_mem->mem_type == TTM_PL_SYSTEM) { - if (old_mem->mem_type == TTM_PL_SYSTEM) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - if (nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem)) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } else if (old_mem->mem_type == TTM_PL_SYSTEM) { - if (nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem)) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } else { - if (nouveau_bo_move_m2mf(bo, evict, no_wait, old_mem, new_mem)) - return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); - } + /* Hardware assisted copy. */ + if (new_mem->mem_type == TTM_PL_SYSTEM) + ret = nouveau_bo_move_flipd(bo, evict, intr, no_wait, new_mem); + else if (old_mem->mem_type == TTM_PL_SYSTEM) + ret = nouveau_bo_move_flips(bo, evict, intr, no_wait, new_mem); + else + ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem); - return 0; + if (!ret) + goto out; + + /* Fallback to software copy. */ + ret = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); + +out: + if (ret) + nouveau_bo_vm_cleanup(bo, NULL, &new_tile); + else + nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile); + + return ret; } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 446a92ad2ee..9c9815bf505 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -59,11 +59,19 @@ struct nouveau_grctx; #define MAX_NUM_DCB_ENTRIES 16 #define NOUVEAU_MAX_CHANNEL_NR 128 +#define NOUVEAU_MAX_TILE_NR 15 #define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL) #define NV50_VM_BLOCK (512*1024*1024ULL) #define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) +struct nouveau_tile_reg { + struct nouveau_fence *fence; + uint32_t addr; + uint32_t size; + bool used; +}; + struct nouveau_bo { struct ttm_buffer_object bo; struct ttm_placement placement; @@ -83,6 +91,7 @@ struct nouveau_bo { uint32_t tile_mode; uint32_t tile_flags; + struct nouveau_tile_reg *tile; struct drm_gem_object *gem; struct drm_file *cpu_filp; @@ -558,6 +567,12 @@ struct drm_nouveau_private { unsigned long sg_handle; } gart_info; + /* nv10-nv40 tiling regions */ + struct { + struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR]; + spinlock_t lock; + } tile; + /* G8x/G9x virtual address space */ uint64_t vm_gart_base; uint64_t vm_gart_size; @@ -695,6 +710,13 @@ extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); extern int nouveau_mem_init(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); +extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, + uint32_t addr, + uint32_t size, + uint32_t pitch); +extern void nv10_mem_expire_tiling(struct drm_device *dev, + struct nouveau_tile_reg *tile, + struct nouveau_fence *fence); extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, uint32_t size, uint32_t flags, uint64_t phys); diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 5158a12f784..fb9bdd6edf1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -191,6 +191,92 @@ void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap) } } +/* + * NV10-NV40 tiling helpers + */ + +static void +nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = addr; + tile->size = size; + tile->used = !!pitch; + nouveau_fence_unref((void **)&tile->fence); + + if (!pfifo->cache_flush(dev)) + return; + + pfifo->reassign(dev, false); + pfifo->cache_flush(dev); + pfifo->cache_pull(dev, false); + + nouveau_wait_for_idle(dev); + + pgraph->set_region_tiling(dev, i, addr, size, pitch); + pfb->set_region_tiling(dev, i, addr, size, pitch); + + pfifo->cache_pull(dev, true); + pfifo->reassign(dev, true); +} + +struct nouveau_tile_reg * +nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nouveau_tile_reg *tile = dev_priv->tile.reg, *found = NULL; + int i; + + spin_lock(&dev_priv->tile.lock); + + for (i = 0; i < pfb->num_tiles; i++) { + if (tile[i].used) + /* Tile region in use. */ + continue; + + if (tile[i].fence && + !nouveau_fence_signalled(tile[i].fence, NULL)) + /* Pending tile region. */ + continue; + + if (max(tile[i].addr, addr) < + min(tile[i].addr + tile[i].size, addr + size)) + /* Kill an intersecting tile region. */ + nv10_mem_set_region_tiling(dev, i, 0, 0, 0); + + if (pitch && !found) { + /* Free tile region. */ + nv10_mem_set_region_tiling(dev, i, addr, size, pitch); + found = &tile[i]; + } + } + + spin_unlock(&dev_priv->tile.lock); + + return found; +} + +void +nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile, + struct nouveau_fence *fence) +{ + if (fence) { + /* Mark it as pending. */ + tile->fence = fence; + nouveau_fence_ref(fence); + } + + tile->used = false; +} + /* * NV50 VM helpers */ @@ -513,6 +599,7 @@ nouveau_mem_init(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->ttm.bo_list); spin_lock_init(&dev_priv->ttm.bo_list_lock); + spin_lock_init(&dev_priv->tile.lock); dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); -- cgit v1.2.3 From 73cb9276fd189c19558a97600456bd13fa5debe8 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 12:27:11 +0100 Subject: drm/i2c/ch7006: Drop build time dependency to nouveau. This partially reverts e4b41066, as this driver is intended to be useful with any KMS driver for suitable hardware. The missing build dependency that commit workarounded was DRM_KMS_HELPER. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index b1bc1ea182b..1175429da10 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -30,12 +30,11 @@ config DRM_NOUVEAU_DEBUG via debugfs. menu "I2C encoder or helper chips" - depends on DRM && I2C + depends on DRM && DRM_KMS_HELPER && I2C config DRM_I2C_CH7006 tristate "Chrontel ch7006 TV encoder" - depends on DRM_NOUVEAU - default m + default m if DRM_NOUVEAU help Support for Chrontel ch7006 and similar TV encoders, found on some nVidia video cards. -- cgit v1.2.3 From c6af6053be60840dcbb037c3798557cbf71cbb08 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 19:05:00 +0100 Subject: drm/nouveau: Fix "general protection fault" in the flipd/flips eviction path. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 1d6036fabd5..365fc650817 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -584,7 +584,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr, placement.fpfn = placement.lpfn = 0; placement.num_placement = placement.num_busy_placement = 1; - placement.placement = &placement_memtype; + placement.placement = placement.busy_placement = &placement_memtype; tmp_mem = *new_mem; tmp_mem.mm_node = NULL; @@ -622,7 +622,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, placement.fpfn = placement.lpfn = 0; placement.num_placement = placement.num_busy_placement = 1; - placement.placement = &placement_memtype; + placement.placement = placement.busy_placement = &placement_memtype; tmp_mem = *new_mem; tmp_mem.mm_node = NULL; -- cgit v1.2.3 From 69a18c328b762eaec3f8ca3af8c7cbf10b536bf8 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 19:05:38 +0100 Subject: drm/nouveau: No need to force evict=true when swapping evicted BOs back in. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 365fc650817..73af53fe75a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -634,7 +634,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, if (ret) goto out; - ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait, new_mem); + ret = nouveau_bo_move_m2mf(bo, evict, intr, no_wait, new_mem); if (ret) goto out; -- cgit v1.2.3 From aeca15e596eba284c727049d0b9b855b13c48856 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 16 Dec 2009 19:03:28 +0100 Subject: drm/nouveau: Drop redundant placement initialization. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_bo.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 73af53fe75a..5fd462f4940 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -130,7 +130,7 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_bo *nvbo; - int ret, n = 0; + int ret = 0; nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); if (!nvbo) @@ -145,19 +145,11 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); align >>= PAGE_SHIFT; - if (flags & TTM_PL_FLAG_VRAM) - nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING; - if (flags & TTM_PL_FLAG_TT) - nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; nvbo->placement.fpfn = 0; nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0; - nvbo->placement.placement = nvbo->placements; - nvbo->placement.busy_placement = nvbo->placements; - nvbo->placement.num_placement = n; - nvbo->placement.num_busy_placement = n; + nouveau_bo_placement_set(nvbo, flags); nvbo->channel = chan; - nouveau_bo_placement_set(nvbo, flags); ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, ttm_bo_type_device, &nvbo->placement, align, 0, false, NULL, size, nouveau_bo_del_ttm); -- cgit v1.2.3 From fbe36a7a069267b82b7b82a66d79a4406cfa90b2 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 21 Dec 2009 12:16:52 +1000 Subject: drm/nv50: ignore vbios table's claim to the contrary if EDID says >8bpc Should fix dim panel issues reported on Dell M6400/M6500. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index a9263d92a23..90f0bf59fbc 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -690,9 +690,21 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, int pxclk) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_connector *nv_connector = NULL; + struct drm_encoder *encoder; struct nvbios *bios = &dev_priv->VBIOS; uint32_t mc, script = 0, or; + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + if (nv_encoder->dcb != dcbent) + continue; + + nv_connector = nouveau_encoder_connector_get(nv_encoder); + break; + } + or = ffs(dcbent->or) - 1; mc = nv50_display_mode_ctrl(dev, dcbent->type != OUTPUT_ANALOG, or); switch (dcbent->type) { @@ -711,6 +723,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent, } else if (bios->fp.strapless_is_24bit & 1) script |= 0x0200; + + if (nv_connector && nv_connector->edid && + (nv_connector->edid->revision >= 4) && + (nv_connector->edid->input & 0x70) >= 0x20) + script |= 0x0200; } if (nouveau_uscript_lvds >= 0) { -- cgit v1.2.3 From e55ca7e68efc7c2d320cd9975ebc5e0fd27debf0 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 21 Dec 2009 23:00:41 +0100 Subject: drm/nv50: fix fillrect color struct fb_fillrect->color is not a color, but index into pseudo_palette array Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_fbcon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 6bcc6d39e9b..c966ef83485 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -10,6 +10,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; if (info->state != FBINFO_STATE_RUNNING) return; @@ -31,7 +32,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) OUT_RING(chan, 1); } BEGIN_RING(chan, NvSub2D, 0x0588, 1); - OUT_RING(chan, rect->color); + OUT_RING(chan, color); BEGIN_RING(chan, NvSub2D, 0x0600, 4); OUT_RING(chan, rect->dx); OUT_RING(chan, rect->dy); -- cgit v1.2.3 From 02076da97a15bbf7477bffed71d02f726de2afc2 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 17 Dec 2009 18:52:44 +0100 Subject: drm/nouveau: Clean up the nv17-nv4x load detection code a bit. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_drv.h | 6 +----- drivers/gpu/drm/nouveau/nv04_dac.c | 35 +++++++++++++++++++---------------- drivers/gpu/drm/nouveau/nv17_tv.c | 27 +++++++++++++++++---------- 3 files changed, 37 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 9c9815bf505..7da88a92c83 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1074,8 +1074,7 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd, /* nv04_dac.c */ extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry); -extern enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, - struct drm_connector *connector); +extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder); extern int nv04_dac_output_offset(struct drm_encoder *encoder); extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable); @@ -1093,9 +1092,6 @@ extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry); /* nv17_tv.c */ extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry); -extern enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, - struct drm_connector *connector, - uint32_t pin_mask); /* nv04_display.c */ extern int nv04_display_create(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index d9f32879ba3..d0e038d2894 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -212,16 +212,15 @@ out: return connector_status_disconnected; } -enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, - struct drm_connector *connector) +uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; - uint32_t testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput; - int head, present = 0; + int head; #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) if (dcb->type == OUTPUT_TV) { @@ -287,13 +286,7 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); msleep(5); - temp = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); - - if (dcb->type == OUTPUT_TV) - present = (nv17_tv_detect(encoder, connector, temp) - == connector_status_connected); - else - present = temp & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI; + sample = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); temp = NVReadRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL); NVWriteRAMDAC(dev, head, NV_PRAMDAC_TEST_CONTROL, @@ -310,15 +303,25 @@ enum drm_connector_status nv17_dac_detect(struct drm_encoder *encoder, nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); - if (present) { - NV_INFO(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); + return sample; +} + +static enum drm_connector_status +nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; + uint32_t sample = nv17_dac_sample_load(encoder); + + if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { + NV_INFO(dev, "Load detected on output %c\n", + '@' + ffs(dcb->or)); return connector_status_connected; + } else { + return connector_status_disconnected; } - - return connector_status_disconnected; } - static bool nv04_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 81c01353a9f..5fa4242e4c7 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -33,13 +33,15 @@ #include "nouveau_hw.h" #include "nv17_tv.h" -enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, - struct drm_connector *connector, - uint32_t pin_mask) +static enum drm_connector_status +nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) { + struct drm_device *dev = encoder->dev; + struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); + struct dcb_entry *dcb = tv_enc->base.dcb; - tv_enc->pin_mask = pin_mask >> 28 & 0xe; + tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; switch (tv_enc->pin_mask) { case 0x2: @@ -50,7 +52,7 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SVIDEO; break; case 0xe: - if (nouveau_encoder(encoder)->dcb->tvconf.has_component_output) + if (dcb->tvconf.has_component_output) tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_Component; else tv_enc->subconnector = DRM_MODE_SUBCONNECTOR_SCART; @@ -61,11 +63,16 @@ enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, } drm_connector_property_set_value(connector, - encoder->dev->mode_config.tv_subconnector_property, - tv_enc->subconnector); + conf->tv_subconnector_property, + tv_enc->subconnector); - return tv_enc->subconnector ? connector_status_connected : - connector_status_disconnected; + if (tv_enc->subconnector) { + NV_INFO(dev, "Load detected on output %c\n", + '@' + ffs(dcb->or)); + return connector_status_connected; + } else { + return connector_status_disconnected; + } } static const struct { @@ -633,7 +640,7 @@ static struct drm_encoder_helper_funcs nv17_tv_helper_funcs = { .prepare = nv17_tv_prepare, .commit = nv17_tv_commit, .mode_set = nv17_tv_mode_set, - .detect = nv17_dac_detect, + .detect = nv17_tv_detect, }; static struct drm_encoder_slave_funcs nv17_tv_slave_funcs = { -- cgit v1.2.3 From b7f7e41b895afd110d1f5121161fd401eccd98c9 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Thu, 17 Dec 2009 18:57:44 +0100 Subject: drm/nouveau: Implement nv42-nv43 TV load detection. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nv17_tv.c | 90 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 5fa4242e4c7..58b917c3341 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -33,15 +33,103 @@ #include "nouveau_hw.h" #include "nv17_tv.h" +static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t testval, regoffset = nv04_dac_output_offset(encoder); + uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, + fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; + uint32_t sample = 0; + int head; + +#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) + testval = RGB_TEST_DATA(0x82, 0xeb, 0x82); + if (dev_priv->vbios->tvdactestval) + testval = dev_priv->vbios->tvdactestval; + + dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); + head = (dacclk & 0x100) >> 8; + + /* Save the previous state. */ + gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); + gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); + fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); + fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); + fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); + fp_control = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); + test_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); + ctv_1c = NVReadRAMDAC(dev, head, 0x680c1c); + ctv_14 = NVReadRAMDAC(dev, head, 0x680c14); + ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); + + /* Prepare the DAC for load detection. */ + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true); + + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, 1183); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, + NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | + NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 | + NV_PRAMDAC_FP_TG_CONTROL_READ_PROG | + NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | + NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS); + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, 0); + + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, + (dacclk & ~0xff) | 0x22); + msleep(1); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, + (dacclk & ~0xff) | 0x21); + + NVWriteRAMDAC(dev, head, 0x680c1c, 1 << 20); + NVWriteRAMDAC(dev, head, 0x680c14, 4 << 16); + + /* Sample pin 0x4 (usually S-video luma). */ + NVWriteRAMDAC(dev, head, 0x680c6c, testval >> 10 & 0x3ff); + msleep(20); + sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) + & 0x4 << 28; + + /* Sample the remaining pins. */ + NVWriteRAMDAC(dev, head, 0x680c6c, testval & 0x3ff); + msleep(20); + sample |= NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) + & 0xa << 28; + + /* Restore the previous state. */ + NVWriteRAMDAC(dev, head, 0x680c1c, ctv_1c); + NVWriteRAMDAC(dev, head, 0x680c14, ctv_14); + NVWriteRAMDAC(dev, head, 0x680c6c, ctv_6c); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, dacclk); + NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, test_ctrl); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL, fp_control); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); + NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); + nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1); + nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0); + + return sample; +} + static enum drm_connector_status nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_mode_config *conf = &dev->mode_config; struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); struct dcb_entry *dcb = tv_enc->base.dcb; - tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; + if (dev_priv->chipset == 0x42 || + dev_priv->chipset == 0x43) + tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe; + else + tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe; switch (tv_enc->pin_mask) { case 0x2: -- cgit v1.2.3 From 8f71c29e442e013212a98e2b37eb1074c4d1134f Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 22 Dec 2009 18:24:09 +0100 Subject: drm/nouveau: Don't skip card take down on nv0x. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_state.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 6a459139910..a6b573e8982 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -722,8 +722,8 @@ static void nouveau_close(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - /* In the case of an error dev_priv may not be be allocated yet */ - if (dev_priv && dev_priv->card_type) + /* In the case of an error dev_priv may not be allocated yet */ + if (dev_priv) nouveau_card_takedown(dev); } -- cgit v1.2.3 From c2b82924bda0c3de2b49bd3a4d8b6725721820bc Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Fri, 25 Dec 2009 18:51:17 +0100 Subject: drm/nouveau: better alignment of bo sizes and use roundup instead of ALIGN - Aligning to block size should ensure that the extra size is enough. - Using roundup, because not all sizes are powers of two. Signed-off-by: Maarten Maathuis --- drivers/gpu/drm/nouveau/nouveau_bo.c | 8 ++++++-- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 5fd462f4940..a0c9e00e706 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -73,6 +73,7 @@ nouveau_bo_fixup_align(struct drm_device *dev, case 0x4800: case 0x7a00: if (dev_priv->chipset >= 0xA0) { + *size = roundup(*size, 28672); /* This is based on high end cards with 448 bits * memory bus, could be different elsewhere.*/ *size += 6 * 28672; @@ -80,9 +81,11 @@ nouveau_bo_fixup_align(struct drm_device *dev, * but we must also align to page size. */ *align = 2 * 8 * 28672; } else if (dev_priv->chipset >= 0x90) { + *size = roundup(*size, 16384); *size += 3 * 16384; *align = 12 * 16384; } else { + *size = roundup(*size, 8192); *size += 3 * 8192; /* 12 * 8192 is the actual alignment requirement * but we must also align to page size. */ @@ -114,10 +117,11 @@ nouveau_bo_fixup_align(struct drm_device *dev, } } - *size = ALIGN(*size, PAGE_SIZE); + /* ALIGN works only on powers of two. */ + *size = roundup(*size, PAGE_SIZE); if (dev_priv->card_type == NV_50) { - *size = ALIGN(*size, 65536); + *size = roundup(*size, 65536); *align = max(65536, *align); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 84af25c238b..44cbbeeb774 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -212,11 +212,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, mode_cmd.bpp = surface_bpp; mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); - mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256); + mode_cmd.pitch = roundup(mode_cmd.pitch, 256); mode_cmd.depth = surface_depth; size = mode_cmd.pitch * mode_cmd.height; - size = ALIGN(size, PAGE_SIZE); + size = roundup(size, PAGE_SIZE); ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, false, true, &nvbo); -- cgit v1.2.3 From 0a2d090f99c9686e5107ed59533fc4210a9a47d1 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sat, 26 Dec 2009 21:46:36 +0100 Subject: drm/nv50: make the blocksize depend on vram size - This should be better than what we have now. - I'm less sure about the non power of two path. Signed-off-by: Maarten Maathuis --- drivers/gpu/drm/nouveau/nouveau_bo.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a0c9e00e706..e342a418d43 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -33,6 +33,8 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" +#include + static void nouveau_bo_del_ttm(struct ttm_buffer_object *bo) { @@ -67,29 +69,29 @@ nouveau_bo_fixup_align(struct drm_device *dev, * avoid corruption of other buffer objects. */ if (dev_priv->card_type == NV_50) { + uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15; + int i; + switch (tile_flags) { case 0x1800: case 0x2800: case 0x4800: case 0x7a00: - if (dev_priv->chipset >= 0xA0) { - *size = roundup(*size, 28672); - /* This is based on high end cards with 448 bits - * memory bus, could be different elsewhere.*/ - *size += 6 * 28672; - /* 8 * 28672 is the actual alignment requirement - * but we must also align to page size. */ - *align = 2 * 8 * 28672; - } else if (dev_priv->chipset >= 0x90) { - *size = roundup(*size, 16384); - *size += 3 * 16384; - *align = 12 * 16384; + *size = roundup(*size, block_size); + if (is_power_of_2(block_size)) { + *size += 3 * block_size; + for (i = 1; i < 10; i++) { + *align = 12 * i * block_size; + if (!(*align % 65536)) + break; + } } else { - *size = roundup(*size, 8192); - *size += 3 * 8192; - /* 12 * 8192 is the actual alignment requirement - * but we must also align to page size. */ - *align = 2 * 12 * 8192; + *size += 6 * block_size; + for (i = 1; i < 10; i++) { + *align = 8 * i * block_size; + if (!(*align % 65536)) + break; + } } break; default: -- cgit v1.2.3 From ca4362adb4c01807dfcf3f2b3152a7ee36f0d1ca Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 26 Dec 2009 02:42:45 +0100 Subject: drm/nouveau: Allocate a per-channel instance of NV_SW. It will be useful for various synchronization purposes, mostly stolen from "[PATCH] drm/nv50: synchronize user channel after buffer object move on kernel channel" by Maarten Maathuis. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_channel.c | 4 +++- drivers/gpu/drm/nouveau/nouveau_dma.c | 17 +++++++++++++++++ drivers/gpu/drm/nouveau/nouveau_dma.h | 10 ++++++---- drivers/gpu/drm/nouveau/nouveau_drv.h | 20 +++++++++++--------- drivers/gpu/drm/nouveau/nouveau_object.c | 2 +- drivers/gpu/drm/nouveau/nv04_fbcon.c | 19 ++++++++++--------- 6 files changed, 48 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 9aaa972f882..4f378b68fe7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -414,7 +414,9 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data, init->subchan[0].grclass = 0x0039; else init->subchan[0].grclass = 0x5039; - init->nr_subchan = 1; + init->subchan[1].handle = NvSw; + init->subchan[1].grclass = NV_SW; + init->nr_subchan = 2; /* Named memory object area */ ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 703553687b2..f1fd3f2b981 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -35,6 +35,7 @@ nouveau_dma_init(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *m2mf = NULL; + struct nouveau_gpuobj *nvsw = NULL; int ret, i; /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ @@ -47,6 +48,15 @@ nouveau_dma_init(struct nouveau_channel *chan) if (ret) return ret; + /* Create an NV_SW object for various sync purposes */ + ret = nouveau_gpuobj_sw_new(chan, NV_SW, &nvsw); + if (ret) + return ret; + + ret = nouveau_gpuobj_ref_add(dev, chan, NvSw, nvsw, NULL); + if (ret) + return ret; + /* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */ ret = nouveau_notifier_alloc(chan, NvNotify0, 32, &chan->m2mf_ntfy); if (ret) @@ -87,6 +97,13 @@ nouveau_dma_init(struct nouveau_channel *chan) BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); OUT_RING(chan, NvNotify0); + /* Initialise NV_SW */ + ret = RING_SPACE(chan, 2); + if (ret) + return ret; + BEGIN_RING(chan, NvSubSw, 0, 1); + OUT_RING(chan, NvSw); + /* Sit back and pray the channel works.. */ FIRE_RING(chan); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index 04e85d8f757..dabfd655f93 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -46,10 +46,11 @@ /* Hardcoded object assignments to subchannels (subchannel id). */ enum { NvSubM2MF = 0, - NvSub2D = 1, - NvSubCtxSurf2D = 1, - NvSubGdiRect = 2, - NvSubImageBlit = 3 + NvSubSw = 1, + NvSub2D = 2, + NvSubCtxSurf2D = 2, + NvSubGdiRect = 3, + NvSubImageBlit = 4 }; /* Object handles. */ @@ -67,6 +68,7 @@ enum { NvClipRect = 0x8000000b, NvGdiRect = 0x8000000c, NvImageBlit = 0x8000000d, + NvSw = 0x8000000e, /* G80+ display objects */ NvEvoVRAM = 0x01000000, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 7da88a92c83..9181eaefe91 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -788,6 +788,8 @@ extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, uint32_t *o_ret); extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, struct nouveau_gpuobj **); +extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class, + struct nouveau_gpuobj **); extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, struct drm_file *); extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, @@ -1330,14 +1332,14 @@ nv_two_reg_pll(struct drm_device *dev) return false; } -#define NV50_NVSW 0x0000506e -#define NV50_NVSW_DMA_SEMAPHORE 0x00000060 -#define NV50_NVSW_SEMAPHORE_OFFSET 0x00000064 -#define NV50_NVSW_SEMAPHORE_ACQUIRE 0x00000068 -#define NV50_NVSW_SEMAPHORE_RELEASE 0x0000006c -#define NV50_NVSW_DMA_VBLSEM 0x0000018c -#define NV50_NVSW_VBLSEM_OFFSET 0x00000400 -#define NV50_NVSW_VBLSEM_RELEASE_VALUE 0x00000404 -#define NV50_NVSW_VBLSEM_RELEASE 0x00000408 +#define NV_SW 0x0000506e +#define NV_SW_DMA_SEMAPHORE 0x00000060 +#define NV_SW_SEMAPHORE_OFFSET 0x00000064 +#define NV_SW_SEMAPHORE_ACQUIRE 0x00000068 +#define NV_SW_SEMAPHORE_RELEASE 0x0000006c +#define NV_SW_DMA_VBLSEM 0x0000018c +#define NV_SW_VBLSEM_OFFSET 0x00000400 +#define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 +#define NV_SW_VBLSEM_RELEASE 0x00000408 #endif /* __NOUVEAU_DRV_H__ */ diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 93379bb81be..6c2cf81716d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c @@ -881,7 +881,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, return 0; } -static int +int nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, struct nouveau_gpuobj **gpuobj_ret) { diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index 09a31071ee5..d2d7f0838dc 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -184,6 +184,7 @@ nv04_fbcon_accel_init(struct fb_info *info) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + const int sub = NvSubCtxSurf2D; int surface_fmt, pattern_fmt, rect_fmt; int ret; @@ -247,25 +248,25 @@ nv04_fbcon_accel_init(struct fb_info *info) return 0; } - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvCtxSurf2D); - BEGIN_RING(chan, 1, 0x0184, 2); + BEGIN_RING(chan, sub, 0x0184, 2); OUT_RING(chan, NvDmaFB); OUT_RING(chan, NvDmaFB); - BEGIN_RING(chan, 1, 0x0300, 4); + BEGIN_RING(chan, sub, 0x0300, 4); OUT_RING(chan, surface_fmt); OUT_RING(chan, info->fix.line_length | (info->fix.line_length << 16)); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); OUT_RING(chan, info->fix.smem_start - dev->mode_config.fb_base); - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvRop); - BEGIN_RING(chan, 1, 0x0300, 1); + BEGIN_RING(chan, sub, 0x0300, 1); OUT_RING(chan, 0x55); - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvImagePatt); - BEGIN_RING(chan, 1, 0x0300, 8); + BEGIN_RING(chan, sub, 0x0300, 8); OUT_RING(chan, pattern_fmt); #ifdef __BIG_ENDIAN OUT_RING(chan, 2); @@ -279,9 +280,9 @@ nv04_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, ~0); OUT_RING(chan, ~0); - BEGIN_RING(chan, 1, 0x0000, 1); + BEGIN_RING(chan, sub, 0x0000, 1); OUT_RING(chan, NvClipRect); - BEGIN_RING(chan, 1, 0x0300, 2); + BEGIN_RING(chan, sub, 0x0300, 2); OUT_RING(chan, 0); OUT_RING(chan, (info->var.yres_virtual << 16) | info->var.xres_virtual); -- cgit v1.2.3 From a5027ccd3c1abe190d2b84a2d7e40d5f099e48a7 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 26 Dec 2009 02:09:36 +0100 Subject: drm/nouveau: Use the software object for fencing. This should avoid a race condition on nv0x, if we're doing it with actual PGRAPH objects and a there's a fence within the FIFO DMA fetch area when a context switch kicks in. In that case we get an ILLEGAL_MTHD interrupt as expected, but the values in PGRAPH_TRAPPED_ADDR aren't calculated correctly and they're almost useless (e.g. you can see ILLEGAL_MTHDs for the now inactive channel, with a wrong offset/data pair). Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +- drivers/gpu/drm/nouveau/nv04_graph.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index dacac9a0842..faddf53ff9e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -142,7 +142,7 @@ nouveau_fence_emit(struct nouveau_fence *fence) list_add_tail(&fence->entry, &chan->fence.pending); spin_unlock_irqrestore(&chan->fence.lock, flags); - BEGIN_RING(chan, NvSubM2MF, USE_REFCNT ? 0x0050 : 0x0150, 1); + BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1); OUT_RING(chan, fence->sequence); FIRE_RING(chan); diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index d561d773c0f..82c77f9d469 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -547,7 +547,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, return 0; } -static struct nouveau_pgraph_object_method nv04_graph_mthds_m2mf[] = { +static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = { { 0x0150, nv04_graph_mthd_set_ref }, {} }; @@ -558,7 +558,7 @@ static struct nouveau_pgraph_object_method nv04_graph_mthds_set_operation[] = { }; struct nouveau_pgraph_object_class nv04_graph_grclass[] = { - { 0x0039, false, nv04_graph_mthds_m2mf }, + { 0x0039, false, NULL }, { 0x004a, false, nv04_graph_mthds_set_operation }, /* gdirect */ { 0x005f, false, nv04_graph_mthds_set_operation }, /* imageblit */ { 0x0061, false, nv04_graph_mthds_set_operation }, /* ifc */ @@ -574,6 +574,7 @@ struct nouveau_pgraph_object_class nv04_graph_grclass[] = { { 0x0053, false, NULL }, /* surf3d */ { 0x0054, false, NULL }, /* tex_tri */ { 0x0055, false, NULL }, /* multitex_tri */ + { 0x506e, true, nv04_graph_mthds_sw }, {} }; -- cgit v1.2.3 From ea911a1cf4f9c5bef18ff399ee2e2ec77792b650 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sat, 26 Dec 2009 14:39:46 +0100 Subject: drm/nv04: Context switching fixes. Signed-off-by: Francisco Jerez --- drivers/gpu/drm/nouveau/nv04_graph.c | 152 ++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 82c77f9d469..98f3b40318d 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -28,6 +28,10 @@ #include "nouveau_drv.h" static uint32_t nv04_graph_ctx_regs[] = { + 0x0040053c, + 0x00400544, + 0x00400540, + 0x00400548, NV04_PGRAPH_CTX_SWITCH1, NV04_PGRAPH_CTX_SWITCH2, NV04_PGRAPH_CTX_SWITCH3, @@ -102,69 +106,69 @@ static uint32_t nv04_graph_ctx_regs[] = { NV04_PGRAPH_PATT_COLOR0, NV04_PGRAPH_PATT_COLOR1, NV04_PGRAPH_PATT_COLORRAM+0x00, - NV04_PGRAPH_PATT_COLORRAM+0x01, - NV04_PGRAPH_PATT_COLORRAM+0x02, - NV04_PGRAPH_PATT_COLORRAM+0x03, NV04_PGRAPH_PATT_COLORRAM+0x04, - NV04_PGRAPH_PATT_COLORRAM+0x05, - NV04_PGRAPH_PATT_COLORRAM+0x06, - NV04_PGRAPH_PATT_COLORRAM+0x07, NV04_PGRAPH_PATT_COLORRAM+0x08, - NV04_PGRAPH_PATT_COLORRAM+0x09, - NV04_PGRAPH_PATT_COLORRAM+0x0A, - NV04_PGRAPH_PATT_COLORRAM+0x0B, - NV04_PGRAPH_PATT_COLORRAM+0x0C, - NV04_PGRAPH_PATT_COLORRAM+0x0D, - NV04_PGRAPH_PATT_COLORRAM+0x0E, - NV04_PGRAPH_PATT_COLORRAM+0x0F, + NV04_PGRAPH_PATT_COLORRAM+0x0c, NV04_PGRAPH_PATT_COLORRAM+0x10, - NV04_PGRAPH_PATT_COLORRAM+0x11, - NV04_PGRAPH_PATT_COLORRAM+0x12, - NV04_PGRAPH_PATT_COLORRAM+0x13, NV04_PGRAPH_PATT_COLORRAM+0x14, - NV04_PGRAPH_PATT_COLORRAM+0x15, - NV04_PGRAPH_PATT_COLORRAM+0x16, - NV04_PGRAPH_PATT_COLORRAM+0x17, NV04_PGRAPH_PATT_COLORRAM+0x18, - NV04_PGRAPH_PATT_COLORRAM+0x19, - NV04_PGRAPH_PATT_COLORRAM+0x1A, - NV04_PGRAPH_PATT_COLORRAM+0x1B, - NV04_PGRAPH_PATT_COLORRAM+0x1C, - NV04_PGRAPH_PATT_COLORRAM+0x1D, - NV04_PGRAPH_PATT_COLORRAM+0x1E, - NV04_PGRAPH_PATT_COLORRAM+0x1F, + NV04_PGRAPH_PATT_COLORRAM+0x1c, NV04_PGRAPH_PATT_COLORRAM+0x20, - NV04_PGRAPH_PATT_COLORRAM+0x21, - NV04_PGRAPH_PATT_COLORRAM+0x22, - NV04_PGRAPH_PATT_COLORRAM+0x23, NV04_PGRAPH_PATT_COLORRAM+0x24, - NV04_PGRAPH_PATT_COLORRAM+0x25, - NV04_PGRAPH_PATT_COLORRAM+0x26, - NV04_PGRAPH_PATT_COLORRAM+0x27, NV04_PGRAPH_PATT_COLORRAM+0x28, - NV04_PGRAPH_PATT_COLORRAM+0x29, - NV04_PGRAPH_PATT_COLORRAM+0x2A, - NV04_PGRAPH_PATT_COLORRAM+0x2B, - NV04_PGRAPH_PATT_COLORRAM+0x2C, - NV04_PGRAPH_PATT_COLORRAM+0x2D, - NV04_PGRAPH_PATT_COLORRAM+0x2E, - NV04_PGRAPH_PATT_COLORRAM+0x2F, + NV04_PGRAPH_PATT_COLORRAM+0x2c, NV04_PGRAPH_PATT_COLORRAM+0x30, - NV04_PGRAPH_PATT_COLORRAM+0x31, - NV04_PGRAPH_PATT_COLORRAM+0x32, - NV04_PGRAPH_PATT_COLORRAM+0x33, NV04_PGRAPH_PATT_COLORRAM+0x34, - NV04_PGRAPH_PATT_COLORRAM+0x35, - NV04_PGRAPH_PATT_COLORRAM+0x36, - NV04_PGRAPH_PATT_COLORRAM+0x37, NV04_PGRAPH_PATT_COLORRAM+0x38, - NV04_PGRAPH_PATT_COLORRAM+0x39, - NV04_PGRAPH_PATT_COLORRAM+0x3A, - NV04_PGRAPH_PATT_COLORRAM+0x3B, - NV04_PGRAPH_PATT_COLORRAM+0x3C, - NV04_PGRAPH_PATT_COLORRAM+0x3D, - NV04_PGRAPH_PATT_COLORRAM+0x3E, - NV04_PGRAPH_PATT_COLORRAM+0x3F, + NV04_PGRAPH_PATT_COLORRAM+0x3c, + NV04_PGRAPH_PATT_COLORRAM+0x40, + NV04_PGRAPH_PATT_COLORRAM+0x44, + NV04_PGRAPH_PATT_COLORRAM+0x48, + NV04_PGRAPH_PATT_COLORRAM+0x4c, + NV04_PGRAPH_PATT_COLORRAM+0x50, + NV04_PGRAPH_PATT_COLORRAM+0x54, + NV04_PGRAPH_PATT_COLORRAM+0x58, + NV04_PGRAPH_PATT_COLORRAM+0x5c, + NV04_PGRAPH_PATT_COLORRAM+0x60, + NV04_PGRAPH_PATT_COLORRAM+0x64, + NV04_PGRAPH_PATT_COLORRAM+0x68, + NV04_PGRAPH_PATT_COLORRAM+0x6c, + NV04_PGRAPH_PATT_COLORRAM+0x70, + NV04_PGRAPH_PATT_COLORRAM+0x74, + NV04_PGRAPH_PATT_COLORRAM+0x78, + NV04_PGRAPH_PATT_COLORRAM+0x7c, + NV04_PGRAPH_PATT_COLORRAM+0x80, + NV04_PGRAPH_PATT_COLORRAM+0x84, + NV04_PGRAPH_PATT_COLORRAM+0x88, + NV04_PGRAPH_PATT_COLORRAM+0x8c, + NV04_PGRAPH_PATT_COLORRAM+0x90, + NV04_PGRAPH_PATT_COLORRAM+0x94, + NV04_PGRAPH_PATT_COLORRAM+0x98, + NV04_PGRAPH_PATT_COLORRAM+0x9c, + NV04_PGRAPH_PATT_COLORRAM+0xa0, + NV04_PGRAPH_PATT_COLORRAM+0xa4, + NV04_PGRAPH_PATT_COLORRAM+0xa8, + NV04_PGRAPH_PATT_COLORRAM+0xac, + NV04_PGRAPH_PATT_COLORRAM+0xb0, + NV04_PGRAPH_PATT_COLORRAM+0xb4, + NV04_PGRAPH_PATT_COLORRAM+0xb8, + NV04_PGRAPH_PATT_COLORRAM+0xbc, + NV04_PGRAPH_PATT_COLORRAM+0xc0, + NV04_PGRAPH_PATT_COLORRAM+0xc4, + NV04_PGRAPH_PATT_COLORRAM+0xc8, + NV04_PGRAPH_PATT_COLORRAM+0xcc, + NV04_PGRAPH_PATT_COLORRAM+0xd0, + NV04_PGRAPH_PATT_COLORRAM+0xd4, + NV04_PGRAPH_PATT_COLORRAM+0xd8, + NV04_PGRAPH_PATT_COLORRAM+0xdc, + NV04_PGRAPH_PATT_COLORRAM+0xe0, + NV04_PGRAPH_PATT_COLORRAM+0xe4, + NV04_PGRAPH_PATT_COLORRAM+0xe8, + NV04_PGRAPH_PATT_COLORRAM+0xec, + NV04_PGRAPH_PATT_COLORRAM+0xf0, + NV04_PGRAPH_PATT_COLORRAM+0xf4, + NV04_PGRAPH_PATT_COLORRAM+0xf8, + NV04_PGRAPH_PATT_COLORRAM+0xfc, NV04_PGRAPH_PATTERN, 0x0040080c, NV04_PGRAPH_PATTERN_SHAPE, @@ -247,14 +251,6 @@ static uint32_t nv04_graph_ctx_regs[] = { 0x004004f8, 0x0040047c, 0x004004fc, - 0x0040053c, - 0x00400544, - 0x00400540, - 0x00400548, - 0x00400560, - 0x00400568, - 0x00400564, - 0x0040056c, 0x00400534, 0x00400538, 0x00400514, @@ -341,9 +337,8 @@ static uint32_t nv04_graph_ctx_regs[] = { 0x00400500, 0x00400504, NV04_PGRAPH_VALID1, - NV04_PGRAPH_VALID2 - - + NV04_PGRAPH_VALID2, + NV04_PGRAPH_DEBUG_3 }; struct graph_state { @@ -388,6 +383,18 @@ nv04_graph_context_switch(struct drm_device *dev) pgraph->fifo_access(dev, true); } +static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) { + if (nv04_graph_ctx_regs[i] == reg) + return &ctx->nv04[i]; + } + + return NULL; +} + int nv04_graph_create_context(struct nouveau_channel *chan) { struct graph_state *pgraph_ctx; @@ -398,15 +405,8 @@ int nv04_graph_create_context(struct nouveau_channel *chan) if (pgraph_ctx == NULL) return -ENOMEM; - /* dev_priv->fifos[channel].pgraph_ctx_user = channel << 24; */ - pgraph_ctx->nv04[0] = 0x0001ffff; - /* is it really needed ??? */ -#if 0 - dev_priv->fifos[channel].pgraph_ctx[1] = - nv_rd32(dev, NV_PGRAPH_DEBUG_4); - dev_priv->fifos[channel].pgraph_ctx[2] = - nv_rd32(dev, 0x004006b0); -#endif + *ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31; + return 0; } @@ -429,9 +429,13 @@ int nv04_graph_load_context(struct nouveau_channel *chan) nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]); nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100); - nv_wr32(dev, NV04_PGRAPH_CTX_USER, chan->id << 24); + + tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; + nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24); + tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2); nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff); + return 0; } @@ -494,7 +498,7 @@ int nv04_graph_init(struct drm_device *dev) nv_wr32(dev, NV04_PGRAPH_STATE , 0xFFFFFFFF); nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL , 0x10000100); tmp = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff; - tmp |= dev_priv->engine.fifo.channels << 24; + tmp |= (dev_priv->engine.fifo.channels - 1) << 24; nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp); /* These don't belong here, they're part of a per-channel context */ -- cgit v1.2.3 From 7de3643f938af910bef4c1f800176a3ebdc29502 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jan 2010 09:10:55 +1000 Subject: drm/nouveau: fix handling of fbcon colours in 8bpp Depending on the visual, the colours handed to us in fillrect() can either be an actual colour, or an index into the pseudo-palette. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_fbcon.c | 7 +++++-- drivers/gpu/drm/nouveau/nv50_fbcon.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index d2d7f0838dc..bd08a0dc984 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -62,7 +62,6 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; - uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; if (info->state != FBINFO_STATE_RUNNING) return; @@ -80,7 +79,11 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); BEGIN_RING(chan, NvSubGdiRect, 0x03fc, 1); - OUT_RING(chan, color); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) + OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]); + else + OUT_RING(chan, rect->color); BEGIN_RING(chan, NvSubGdiRect, 0x0400, 2); OUT_RING(chan, (rect->dx << 16) | rect->dy); OUT_RING(chan, (rect->width << 16) | rect->height); diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index c966ef83485..cc34356ab0b 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -10,7 +10,6 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) struct drm_device *dev = par->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; - uint32_t color = ((uint32_t *) info->pseudo_palette)[rect->color]; if (info->state != FBINFO_STATE_RUNNING) return; @@ -32,7 +31,11 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) OUT_RING(chan, 1); } BEGIN_RING(chan, NvSub2D, 0x0588, 1); - OUT_RING(chan, color); + if (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) + OUT_RING(chan, ((uint32_t *)info->pseudo_palette)[rect->color]); + else + OUT_RING(chan, rect->color); BEGIN_RING(chan, NvSub2D, 0x0600, 4); OUT_RING(chan, rect->dx); OUT_RING(chan, rect->dy); -- cgit v1.2.3 From e9dd8e11edfff5e348f3dcfd152a70c5da921126 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jan 2010 12:53:01 +1000 Subject: drm/nouveau: remove unused nouveau_channel_idle() function Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_channel.c | 41 ------------------------------- drivers/gpu/drm/nouveau/nouveau_drv.h | 1 - 2 files changed, 42 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 4f378b68fe7..d1c7f8c911c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -235,47 +235,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return 0; } -int -nouveau_channel_idle(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - uint32_t caches; - int idle; - - if (!chan) { - NV_ERROR(dev, "no channel...\n"); - return 1; - } - - caches = nv_rd32(dev, NV03_PFIFO_CACHES); - nv_wr32(dev, NV03_PFIFO_CACHES, caches & ~1); - - if (engine->fifo.channel_id(dev) != chan->id) { - struct nouveau_gpuobj *ramfc = - chan->ramfc ? chan->ramfc->gpuobj : NULL; - - if (!ramfc) { - NV_ERROR(dev, "No RAMFC for channel %d\n", chan->id); - return 1; - } - - engine->instmem.prepare_access(dev, false); - if (nv_ro32(dev, ramfc, 0) != nv_ro32(dev, ramfc, 1)) - idle = 0; - else - idle = 1; - engine->instmem.finish_access(dev); - } else { - idle = (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET) == - nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT)); - } - - nv_wr32(dev, NV03_PFIFO_CACHES, caches); - return idle; -} - /* stops a fifo */ void nouveau_channel_free(struct nouveau_channel *chan) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 9181eaefe91..4087a9a20ba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -745,7 +745,6 @@ extern int nouveau_channel_alloc(struct drm_device *dev, struct drm_file *file_priv, uint32_t fb_ctxdma, uint32_t tt_ctxdma); extern void nouveau_channel_free(struct nouveau_channel *); -extern int nouveau_channel_idle(struct nouveau_channel *chan); /* nouveau_object.c */ extern int nouveau_gpuobj_early_init(struct drm_device *); -- cgit v1.2.3 From c03ec7f91fcf20af177dbc728d518fb462bad42d Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 4 Jan 2010 19:25:09 +0100 Subject: drm/nouveau: create function for "dealing" with gpu lockup It's mostly a cleanup, but in nv50_fbcon_accel_init gpu lockup message was printed, but HWACCEL_DISBALED flag was not set. Signed-off-by: Marcin Slusarz Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 15 +++++++++++---- drivers/gpu/drm/nouveau/nouveau_fbcon.h | 1 + drivers/gpu/drm/nouveau/nv04_fbcon.c | 15 +++++---------- drivers/gpu/drm/nouveau/nv50_fbcon.c | 17 +++++------------ 4 files changed, 22 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 44cbbeeb774..0b05c869e0e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -64,8 +64,7 @@ nouveau_fbcon_sync(struct fb_info *info) return 0; if (RING_SPACE(chan, 4)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); return 0; } @@ -86,8 +85,7 @@ nouveau_fbcon_sync(struct fb_info *info) } if (ret) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); return 0; } @@ -380,3 +378,12 @@ nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb) return 0; } + +void nouveau_fbcon_gpu_lockup(struct fb_info *info) +{ + struct nouveau_fbcon_par *par = info->par; + struct drm_device *dev = par->dev; + + NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + info->flags |= FBINFO_HWACCEL_DISABLED; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index 8531140fedb..462e0b87b4b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -43,5 +43,6 @@ void nouveau_fbcon_zfill(struct drm_device *dev); int nv04_fbcon_accel_init(struct fb_info *info); int nv50_fbcon_accel_init(struct fb_info *info); +void nouveau_fbcon_gpu_lockup(struct fb_info *info); #endif /* __NV50_FBCON_H__ */ diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c index bd08a0dc984..d910873c136 100644 --- a/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -39,8 +39,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) return; if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -67,8 +66,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) return; if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -112,8 +110,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) } if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -147,8 +144,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) int iter_len = dsize > 128 ? 128 : dsize; if (RING_SPACE(chan, iter_len + 1)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); cfb_imageblit(info, image); return; } @@ -246,8 +242,7 @@ nv04_fbcon_accel_init(struct fb_info *info) return ret; if (RING_SPACE(chan, 49)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); return 0; } diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index cc34356ab0b..e4f279ee61c 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -16,9 +16,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -60,9 +58,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) return; if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -105,8 +101,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) } if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); } if (info->flags & FBINFO_HWACCEL_DISABLED) { @@ -139,9 +134,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) int push = dwords > 2047 ? 2047 : dwords; if (RING_SPACE(chan, push + 1)) { - NV_ERROR(dev, - "GPU lockup - switching to software fbcon\n"); - info->flags |= FBINFO_HWACCEL_DISABLED; + nouveau_fbcon_gpu_lockup(info); cfb_imageblit(info, image); return; } @@ -203,7 +196,7 @@ nv50_fbcon_accel_init(struct fb_info *info) ret = RING_SPACE(chan, 59); if (ret) { - NV_ERROR(dev, "GPU lockup - switching to software fbcon\n"); + nouveau_fbcon_gpu_lockup(info); return ret; } -- cgit v1.2.3 From a908b96c22883f967e4ddf5aa5b35e3b4a0629a5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 5 Jan 2010 09:41:05 +1000 Subject: drm/nv50: restore correct cache1 get/put address on fifoctx load Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_fifo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index b7282284f08..39caf167587 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -384,8 +384,8 @@ nv50_fifo_load_context(struct nouveau_channel *chan) nv_wr32(dev, NV40_PFIFO_CACHE1_DATA(ptr), nv_ro32(dev, cache, (ptr * 2) + 1)); } - nv_wr32(dev, 0x3210, cnt << 2); - nv_wr32(dev, 0x3270, 0); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, cnt << 2); + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); /* guessing that all the 0x34xx regs aren't on NV50 */ if (!IS_G80) { @@ -398,8 +398,6 @@ nv50_fifo_load_context(struct nouveau_channel *chan) dev_priv->engine.instmem.finish_access(dev); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0); nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, chan->id | (1<<16)); return 0; } -- cgit v1.2.3 From 1959ca80e1f88b82c1cb7227f437910768ab0c94 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 4 Jan 2010 15:52:20 +1000 Subject: drm/nouveau: have ttm's fault handler called directly There's no good reason for us to have our own anymore, this is left over from an early port to these TTM interfaces. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_ttm.c | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 187eb84e4da..c385d50f041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -28,45 +28,17 @@ #include "nouveau_drv.h" -static struct vm_operations_struct nouveau_ttm_vm_ops; -static const struct vm_operations_struct *ttm_vm_ops; - -static int -nouveau_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct ttm_buffer_object *bo = vma->vm_private_data; - int ret; - - if (unlikely(bo == NULL)) - return VM_FAULT_NOPAGE; - - ret = ttm_vm_ops->fault(vma, vmf); - return ret; -} - int nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; struct drm_nouveau_private *dev_priv = file_priv->minor->dev->dev_private; - int ret; if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) return drm_mmap(filp, vma); - ret = ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); - if (unlikely(ret != 0)) - return ret; - - if (unlikely(ttm_vm_ops == NULL)) { - ttm_vm_ops = vma->vm_ops; - nouveau_ttm_vm_ops = *ttm_vm_ops; - nouveau_ttm_vm_ops.fault = &nouveau_ttm_fault; - } - - vma->vm_ops = &nouveau_ttm_vm_ops; - return 0; + return ttm_bo_mmap(filp, vma, &dev_priv->ttm.bdev); } static int -- cgit v1.2.3 From dc8d76cac942e7344a72ad18afb90fa46cf20bb4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 6 Jan 2010 12:00:02 +1000 Subject: drm/nv50: prevent a possible ctxprog hang The below is mainly an educated guess at what's going on, docs would sure be handy... NVIDIA? :P It appears it's possible for a ctxprog to run even while a GPU exception is pending. The GF8 and up ctxprogs appear to have a small snippet of code which detects this, and stalls the ctxprog until it's been handled, which essentially looks like: if (r2 & 0x00008000) { r0 |= 0x80000000; while (r0 & 0x80000000) {} } I don't know of any way that flag would get cleared unless the driver intervenes (and indeed, in the cases I've seen the hang, nothing steps in to automagically clear it for us). This patch causes the driver to clear the flag during the PGRAPH IRQ handler. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_irq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 370c72c968d..919a619ca7f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -635,6 +635,7 @@ nv50_pgraph_irq_handler(struct drm_device *dev) if ((nv_rd32(dev, 0x400500) & isb) != isb) nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb); + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); } nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); -- cgit v1.2.3 From d6126c5c8b2019658aadc9754dca80a7573dbff5 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 6 Jan 2010 04:02:45 +0100 Subject: drm/nouveau: Fix null deref in nouveau_fence_emit due to deleted fence Currently Nouveau will unvalidate all buffers if it is forced to wait on one, and then start revalidating from the beginning. While doing so, it destroys the operation fence, causing nouveau_fence_emit to crash. This patch fixes this bug by taking the fence object out of validate_op and creating it just before emit. The fence pointer is initialized to 0 and unref'ed unconditionally. In addition to fixing the bug, this prevents its reintroduction and simplifies the code. Signed-off-by: Luca Barbieri Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_gem.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 18fd8ac9fca..2009db2426c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -220,7 +220,6 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, } struct validate_op { - struct nouveau_fence *fence; struct list_head vram_list; struct list_head gart_list; struct list_head both_list; @@ -252,17 +251,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) } static void -validate_fini(struct validate_op *op, bool success) +validate_fini(struct validate_op *op, struct nouveau_fence* fence) { - struct nouveau_fence *fence = op->fence; - - if (unlikely(!success)) - op->fence = NULL; - - validate_fini_list(&op->vram_list, op->fence); - validate_fini_list(&op->gart_list, op->fence); - validate_fini_list(&op->both_list, op->fence); - nouveau_fence_unref((void *)&fence); + validate_fini_list(&op->vram_list, fence); + validate_fini_list(&op->gart_list, fence); + validate_fini_list(&op->both_list, fence); } static int @@ -420,10 +413,6 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, INIT_LIST_HEAD(&op->gart_list); INIT_LIST_HEAD(&op->both_list); - ret = nouveau_fence_new(chan, &op->fence, false); - if (ret) - return ret; - if (nr_buffers == 0) return 0; @@ -541,6 +530,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct drm_nouveau_gem_pushbuf_bo *bo = NULL; struct nouveau_channel *chan; struct validate_op op; + struct nouveau_fence* fence = 0; uint32_t *pushbuf = NULL; int ret = 0, do_reloc = 0, i; @@ -597,7 +587,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, OUT_RINGp(chan, pushbuf, req->nr_dwords); - ret = nouveau_fence_emit(op.fence); + ret = nouveau_fence_new(chan, &fence, true); if (ret) { NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); @@ -605,7 +595,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } if (nouveau_gem_pushbuf_sync(chan)) { - ret = nouveau_fence_wait(op.fence, NULL, false, false); + ret = nouveau_fence_wait(fence, NULL, false, false); if (ret) { for (i = 0; i < req->nr_dwords; i++) NV_ERROR(dev, "0x%08x\n", pushbuf[i]); @@ -614,7 +604,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } out: - validate_fini(&op, ret == 0); + validate_fini(&op, fence); + nouveau_fence_unref((void**)&fence); mutex_unlock(&dev->struct_mutex); kfree(pushbuf); kfree(bo); @@ -634,6 +625,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, struct drm_gem_object *gem; struct nouveau_bo *pbbo; struct validate_op op; + struct nouveau_fence* fence = 0; int i, ret = 0, do_reloc = 0; NOUVEAU_CHECK_INITIALISED_WITH_RETURN; @@ -772,7 +764,7 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, OUT_RING(chan, 0); } - ret = nouveau_fence_emit(op.fence); + ret = nouveau_fence_new(chan, &fence, true); if (ret) { NV_ERROR(dev, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); @@ -780,7 +772,8 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, } out: - validate_fini(&op, ret == 0); + validate_fini(&op, fence); + nouveau_fence_unref((void**)&fence); mutex_unlock(&dev->struct_mutex); kfree(bo); -- cgit v1.2.3 From cc6e496587502057af02139931736b0b7a49f637 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 7 Jan 2010 13:47:57 +1000 Subject: drm/nv04: differentiate between nv04/nv05 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index a6b573e8982..09b9a46dfc0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -642,7 +642,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev_priv->chipset = (reg0 & 0xff00000) >> 20; /* NV04 or NV05 */ } else if ((reg0 & 0xff00fff0) == 0x20004000) { - dev_priv->chipset = 0x04; + if (reg0 & 0x00f00000) + dev_priv->chipset = 0x05; + else + dev_priv->chipset = 0x04; } else dev_priv->chipset = 0xff; -- cgit v1.2.3 From 400f14ac4ef02b2f77c9d0e3ad7d66e2f6c8e663 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 8 Jan 2010 10:53:40 +1000 Subject: drm/nouveau: use dma.max rather than pushbuf size for checking GET validity Some upcoming G80 DMA changes will depend on this, but it's split out for bisectibility just in case it causes some unexpected issues. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index f1fd3f2b981..3f7f78e03d4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -130,7 +130,7 @@ READ_GET(struct nouveau_channel *chan, uint32_t *get) val = nvchan_rd32(chan, chan->user_get); if (val < chan->pushbuf_base || - val >= chan->pushbuf_base + chan->pushbuf_bo->bo.mem.size) { + val > chan->pushbuf_base + (chan->dma.max << 2)) { /* meaningless to dma_wait() except to know whether the * GPU has stalled or not */ -- cgit v1.2.3 From c63834e1db41b59d6c7bfb1d2a549c027a42a877 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 8 Jan 2010 10:57:39 +1000 Subject: drm/nouveau: initialise DMA tracking parameters earlier Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_channel.c | 2 ++ drivers/gpu/drm/nouveau/nouveau_dma.c | 15 +++++++++------ drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index d1c7f8c911c..343d718a966 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -158,6 +158,8 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return ret; } + nouveau_dma_pre_init(chan); + /* Locate channel's user control regs */ if (dev_priv->card_type < NV_40) user = NV03_USER(channel); diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 3f7f78e03d4..7afbe8b40d5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -29,6 +29,15 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" +void +nouveau_dma_pre_init(struct nouveau_channel *chan) +{ + chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2; + chan->dma.put = 0; + chan->dma.cur = chan->dma.put; + chan->dma.free = chan->dma.max - chan->dma.cur; +} + int nouveau_dma_init(struct nouveau_channel *chan) { @@ -74,12 +83,6 @@ nouveau_dma_init(struct nouveau_channel *chan) return ret; } - /* Initialise DMA vars */ - chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2; - chan->dma.put = 0; - chan->dma.cur = chan->dma.put; - chan->dma.free = chan->dma.max - chan->dma.cur; - /* Insert NOPS for NOUVEAU_DMA_SKIPS */ ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS); if (ret) diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 4087a9a20ba..026419fe879 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -837,6 +837,7 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan) #endif /* nouveau_dma.c */ +extern void nouveau_dma_pre_init(struct nouveau_channel *); extern int nouveau_dma_init(struct nouveau_channel *); extern int nouveau_dma_wait(struct nouveau_channel *, int size); -- cgit v1.2.3 From 40c2298bdcc8b766a39964c44e9a74d16aa95d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Ko=C5=9Bcielnicki?= Date: Sun, 10 Jan 2010 17:09:14 +0000 Subject: drm/nv04: Fix set_operation software method. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 98f3b40318d..e260986ea65 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -537,7 +537,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, int mthd, uint32_t data) { struct drm_device *dev = chan->dev; - uint32_t instance = nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff; + uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; uint32_t tmp; -- cgit v1.2.3 From 3f50b0222e4c6ac59a5c4819f8be0fa500970381 Mon Sep 17 00:00:00 2001 From: Kevin Winchester Date: Tue, 17 Nov 2009 14:38:45 -0800 Subject: agp: correct missing cleanup on error in agp_add_bridge While investigating a kmemleak detected leak, I encountered the agp_add_bridge function. It appears to be responsible for freeing the agp_bridge_data in the case of a failure, but it is only doing so for some errors. Fix it to always free the bridge data if a failure condition is encountered. Signed-off-by: Kevin Winchester Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/agp/backend.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index a56ca080e10..c3ab46da51a 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -285,18 +285,22 @@ int agp_add_bridge(struct agp_bridge_data *bridge) { int error; - if (agp_off) - return -ENODEV; + if (agp_off) { + error = -ENODEV; + goto err_put_bridge; + } if (!bridge->dev) { printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); - return -EINVAL; + error = -EINVAL; + goto err_put_bridge; } /* Grab reference on the chipset driver. */ if (!try_module_get(bridge->driver->owner)) { dev_info(&bridge->dev->dev, "can't lock chipset driver\n"); - return -EINVAL; + error = -EINVAL; + goto err_put_bridge; } error = agp_backend_initialize(bridge); @@ -326,6 +330,7 @@ frontend_err: agp_backend_cleanup(bridge); err_out: module_put(bridge->driver->owner); +err_put_bridge: agp_put_bridge(bridge); return error; } -- cgit v1.2.3 From 67fe63b0715ccfaefa0af8a6e705c5470ee5cada Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 7 Jan 2010 12:58:51 -0700 Subject: agp/hp: fixup hp agp after ACPI changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 15b8dd53f5ffa changed the string in info->hardware_id from a static array to a pointer and added a length field. But instead of changing "sizeof(array)" to "length", we changed it to "sizeof(length)" (== 4), which corrupts the string we're trying to null-terminate. We no longer even need to null-terminate the string, but we *do* need to check whether we found a HID. If there's no HID, we used to have an empty array, but now we have a null pointer. The combination of these defects causes this oops: Unable to handle kernel NULL pointer dereference (address 0000000000000003) modprobe[895]: Oops 8804682956800 [1] ip is at zx1_gart_probe+0xd0/0xcc0 [hp_agp] http://marc.info/?l=linux-ia64&m=126264484923647&w=2 Signed-off-by: Bjorn Helgaas Reported-by: Émeric Maschino Signed-off-by: Dave Airlie --- drivers/char/agp/hp-agp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 9047b271465..dc8a6f70483 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -488,9 +488,8 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) handle = obj; do { status = acpi_get_object_info(handle, &info); - if (ACPI_SUCCESS(status)) { + if (ACPI_SUCCESS(status) && (info->valid & ACPI_VALID_HID)) { /* TBD check _CID also */ - info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0'; match = (strcmp(info->hardware_id.string, "HWP0001") == 0); kfree(info); if (match) { -- cgit v1.2.3 From 3d4a7882b11299104a0e74425dece2e26ac98024 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 7 Jan 2010 12:58:56 -0700 Subject: agp/hp: fail gracefully if we don't find an IOC Bail out if we don't find an enclosing IOC. Previously, if we didn't find one, we tried to set things up using garbage for the SBA/IOC register address, which causes a crash. This crash only happens if firmware supplies a defective ACPI namespace, so it doesn't fix any problems in the field. Signed-off-by: Bjorn Helgaas Signed-off-by: Dave Airlie --- drivers/char/agp/hp-agp.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index dc8a6f70483..58752b70efe 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c @@ -508,6 +508,9 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) handle = parent; } while (ACPI_SUCCESS(status)); + if (ACPI_FAILURE(status)) + return AE_OK; /* found no enclosing IOC */ + if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) return AE_OK; -- cgit v1.2.3 From e6edbdc52bc0755cbfe0721ca91d4fd87649bc13 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 10 Jan 2010 23:59:05 -0800 Subject: Input: i8042 - add Dritek quirk for Acer Aspire 5610. Signed-off-by: Elliott Sales de Andrade Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 64b688daf48..2a5982e532f 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -523,6 +523,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { * have turned up in 2007 that also need this again. */ static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { + { + /* Acer Aspire 5610 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), + }, + }, { /* Acer Aspire 5630 */ .matches = { -- cgit v1.2.3 From fc248a497d83f5aba9d46d7ff114c070fb2a2fa2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 4 Jan 2010 15:23:50 +0200 Subject: OMAP: DSS2: RFBI: convert to new kfifo API Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/rfbi.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index d0b3006ad8a..b936495c065 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -120,7 +120,7 @@ static struct { struct omap_dss_device *dssdev[2]; - struct kfifo *cmd_fifo; + struct kfifo cmd_fifo; spinlock_t cmd_lock; struct completion cmd_done; atomic_t cmd_fifo_full; @@ -1011,20 +1011,20 @@ static void process_cmd_fifo(void) return; while (true) { - spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); + spin_lock_irqsave(&rfbi.cmd_lock, flags); - len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p, + len = kfifo_out(&rfbi.cmd_fifo, (unsigned char *)&p, sizeof(struct update_param)); if (len == 0) { DSSDBG("nothing more in fifo\n"); atomic_set(&rfbi.cmd_pending, 0); - spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + spin_unlock_irqrestore(&rfbi.cmd_lock, flags); break; } /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/ - spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + spin_unlock_irqrestore(&rfbi.cmd_lock, flags); BUG_ON(len != sizeof(struct update_param)); BUG_ON(p.rfbi_module > 1); @@ -1052,25 +1052,25 @@ static void rfbi_push_cmd(struct update_param *p) unsigned long flags; int available; - spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); + spin_lock_irqsave(&rfbi.cmd_lock, flags); available = RFBI_CMD_FIFO_LEN_BYTES - - __kfifo_len(rfbi.cmd_fifo); + kfifo_len(&rfbi.cmd_fifo); /* DSSDBG("%d bytes left in fifo\n", available); */ if (available < sizeof(struct update_param)) { DSSDBG("Going to wait because FIFO FULL..\n"); - spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + spin_unlock_irqrestore(&rfbi.cmd_lock, flags); atomic_inc(&rfbi.cmd_fifo_full); wait_for_completion(&rfbi.cmd_done); /*DSSDBG("Woke up because fifo not full anymore\n");*/ continue; } - ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p, + ret = kfifo_in(&rfbi.cmd_fifo, (unsigned char *)p, sizeof(struct update_param)); /* DSSDBG("pushed %d bytes\n", ret);*/ - spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); + spin_unlock_irqrestore(&rfbi.cmd_lock, flags); BUG_ON(ret != sizeof(struct update_param)); @@ -1155,12 +1155,12 @@ int rfbi_init(void) { u32 rev; u32 l; + int r; spin_lock_init(&rfbi.cmd_lock); - rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL, - &rfbi.cmd_lock); - if (IS_ERR(rfbi.cmd_fifo)) - return -ENOMEM; + r = kfifo_alloc(&rfbi.cmd_fifo, RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL); + if (r) + return r; init_completion(&rfbi.cmd_done); atomic_set(&rfbi.cmd_fifo_full, 0); @@ -1196,7 +1196,7 @@ void rfbi_exit(void) { DSSDBG("rfbi_exit\n"); - kfifo_free(rfbi.cmd_fifo); + kfifo_free(&rfbi.cmd_fifo); iounmap(rfbi.base); } -- cgit v1.2.3 From f778a12dd33200513596a0d4d3ba4d5f09e79c09 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 16 Dec 2009 13:18:07 +0200 Subject: OMAP: OMAPFB: fix clk_get for RFBI omapfb platform device was still used to get clocks inside rfbi.c Signed-off-by: Tomi Valkeinen Tested-by: Sergey Lapin --- drivers/video/omap/dispc.c | 18 +++--------------- drivers/video/omap/omapfb.h | 2 ++ drivers/video/omap/omapfb_main.c | 18 ++++++++++++++++++ drivers/video/omap/rfbi.c | 4 ++-- 4 files changed, 25 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c index c7c6455f1fa..e192b058a68 100644 --- a/drivers/video/omap/dispc.c +++ b/drivers/video/omap/dispc.c @@ -189,11 +189,6 @@ static struct { struct omapfb_color_key color_key; } dispc; -static struct platform_device omapdss_device = { - .name = "omapdss", - .id = -1, -}; - static void enable_lcd_clocks(int enable); static void inline dispc_write_reg(int idx, u32 val) @@ -920,20 +915,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) static int get_dss_clocks(void) { - dispc.dss_ick = clk_get(&omapdss_device.dev, "ick"); + dispc.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick"); if (IS_ERR(dispc.dss_ick)) { dev_err(dispc.fbdev->dev, "can't get ick\n"); return PTR_ERR(dispc.dss_ick); } - dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck"); + dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck"); if (IS_ERR(dispc.dss1_fck)) { dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); clk_put(dispc.dss_ick); return PTR_ERR(dispc.dss1_fck); } - dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck"); + dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_fck"); if (IS_ERR(dispc.dss_54m_fck)) { dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); clk_put(dispc.dss_ick); @@ -1385,12 +1380,6 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, int skip_init = 0; int i; - r = platform_device_register(&omapdss_device); - if (r) { - dev_err(fbdev->dev, "can't register omapdss device\n"); - return r; - } - memset(&dispc, 0, sizeof(dispc)); dispc.base = ioremap(DISPC_BASE, SZ_1K); @@ -1534,7 +1523,6 @@ static void omap_dispc_cleanup(void) free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); put_dss_clocks(); iounmap(dispc.base); - platform_device_unregister(&omapdss_device); } const struct lcd_ctrl omap2_int_ctrl = { diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h index 46e4714014e..af3c9e571ec 100644 --- a/drivers/video/omap/omapfb.h +++ b/drivers/video/omap/omapfb.h @@ -203,6 +203,8 @@ struct omapfb_device { struct omapfb_mem_desc mem_desc; struct fb_info *fb_info[OMAPFB_PLANE_NUM]; + + struct platform_device *dssdev; /* dummy dev for clocks */ }; #ifdef CONFIG_ARCH_OMAP1 diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index c7f59a5ccdb..f74aec91aee 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -83,6 +83,12 @@ static struct caps_table_struct color_caps[] = { { 1 << OMAPFB_COLOR_YUY422, "YUY422", }, }; +/* dummy device for clocks */ +static struct platform_device omapdss_device = { + .name = "omapdss", + .id = -1, +}; + /* * --------------------------------------------------------------------------- * LCD panel @@ -1700,6 +1706,7 @@ static int omapfb_do_probe(struct platform_device *pdev, fbdev->dev = &pdev->dev; fbdev->panel = panel; + fbdev->dssdev = &omapdss_device; platform_set_drvdata(pdev, fbdev); mutex_init(&fbdev->rqueue_mutex); @@ -1814,8 +1821,16 @@ cleanup: static int omapfb_probe(struct platform_device *pdev) { + int r; + BUG_ON(fbdev_pdev != NULL); + r = platform_device_register(&omapdss_device); + if (r) { + dev_err(&pdev->dev, "can't register omapdss device\n"); + return r; + } + /* Delay actual initialization until the LCD is registered */ fbdev_pdev = pdev; if (fbdev_panel != NULL) @@ -1843,6 +1858,9 @@ static int omapfb_remove(struct platform_device *pdev) fbdev->state = OMAPFB_DISABLED; omapfb_free_resources(fbdev, saved_state); + platform_device_unregister(&omapdss_device); + fbdev->dssdev = NULL; + return 0; } diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c index fed7b1bda19..1162603c72e 100644 --- a/drivers/video/omap/rfbi.c +++ b/drivers/video/omap/rfbi.c @@ -83,13 +83,13 @@ static inline u32 rfbi_read_reg(int idx) static int rfbi_get_clocks(void) { - rfbi.dss_ick = clk_get(rfbi.fbdev->dev, "ick"); + rfbi.dss_ick = clk_get(&dispc.fbdev->dssdev->dev, "ick"); if (IS_ERR(rfbi.dss_ick)) { dev_err(rfbi.fbdev->dev, "can't get ick\n"); return PTR_ERR(rfbi.dss_ick); } - rfbi.dss1_fck = clk_get(rfbi.fbdev->dev, "dss1_fck"); + rfbi.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck"); if (IS_ERR(rfbi.dss1_fck)) { dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); clk_put(rfbi.dss_ick); -- cgit v1.2.3 From b64a5a1200e7ac91ac0dff71b0cfbc3ae19de944 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 7 Jan 2010 11:56:14 +0200 Subject: OMAP: OMAPFB: add dummy release function for omapdss This should fix: WARNING: at drivers/base/core.c:131 device_release+0x68/0x7c() Device 'omapdss' does not have a release() function, it is broken and must be fixed. Signed-off-by: Tomi Valkeinen --- drivers/video/omap/omapfb_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index f74aec91aee..2c4f470fa08 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -83,10 +83,17 @@ static struct caps_table_struct color_caps[] = { { 1 << OMAPFB_COLOR_YUY422, "YUY422", }, }; +static void omapdss_release(struct device *dev) +{ +} + /* dummy device for clocks */ static struct platform_device omapdss_device = { .name = "omapdss", .id = -1, + .dev = { + .release = omapdss_release, + }, }; /* -- cgit v1.2.3 From 5c18df85d731196f40784492d36d0baefdedf15a Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 4 Jan 2010 15:34:14 +0100 Subject: OMAP: DSS2: Fix compile warning Signed-off-by: Vaibhav Hiremath Acked-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index dbb0ce243f0..82918eec6d2 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -124,6 +124,7 @@ static void restore_all_ctx(void) dss_clk_disable_all_no_ctx(); } +#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) /* CLOCKS */ static void core_dump_clocks(struct seq_file *s) { @@ -149,6 +150,7 @@ static void core_dump_clocks(struct seq_file *s) clocks[i]->usecount); } } +#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ static int dss_get_clock(struct clk **clock, const char *clk_name) { -- cgit v1.2.3 From 7f000dd4542fcc1a69b429c0af6c6d961d7fb912 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 22 Dec 2009 09:34:49 +0100 Subject: video/omap: add __init/__exit macros to drivers/video/omap/lcd_htcherald.c Trivial patch which adds the __init/__exit macros to the module_init/ module_exit functions of drivers/video/omap/lcd_htcherald.c Please have a look at the small patch and either pull it through your tree, or please ack' it so Jiri can pull it through the trivial tree. Patch against linux-next-tree, 22. Dez 08:38:18 CET 2009 but also present in linus tree. Signed-off-by: Peter Huewe Acked-by: Tony Lindgren --- drivers/video/omap/lcd_htcherald.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c index a9007c5d1fa..4802419da83 100644 --- a/drivers/video/omap/lcd_htcherald.c +++ b/drivers/video/omap/lcd_htcherald.c @@ -115,12 +115,12 @@ struct platform_driver htcherald_panel_driver = { }, }; -static int htcherald_panel_drv_init(void) +static int __init htcherald_panel_drv_init(void) { return platform_driver_register(&htcherald_panel_driver); } -static void htcherald_panel_drv_cleanup(void) +static void __exit htcherald_panel_drv_cleanup(void) { platform_driver_unregister(&htcherald_panel_driver); } -- cgit v1.2.3 From f3a82d11d478a9eb5ff0cfa83796f0ba8149d841 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 7 Jan 2010 13:37:30 +0200 Subject: OMAP: DSS2: OMAPFB: fix omapfb_free_fbmem() Fixes bug causing VRFB memory area to be released twice. Signed-off-by: Tomi Valkeinen Reported-by: Eino-Ville Talvala --- drivers/video/omap2/omapfb/omapfb-main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index ef299839858..e61a75c3135 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1311,6 +1311,7 @@ static void omapfb_free_fbmem(struct fb_info *fbi) if (rg->vrfb.vaddr[0]) { iounmap(rg->vrfb.vaddr[0]); omap_vrfb_release_ctx(&rg->vrfb); + rg->vrfb.vaddr[0] = NULL; } } -- cgit v1.2.3 From 24be78b32f0a6e14aead3eac89d768a361b091b3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 7 Jan 2010 14:19:48 +0200 Subject: OMAP: DSS2: Make check-delay-loops consistent Loops checking for certain condition were rather inconsistent. Signed-off-by: Tomi Valkeinen Reported-by: Juha Leppanen --- drivers/video/omap2/dss/dsi.c | 14 +++++++------- drivers/video/omap2/dss/dss.c | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index e32a53c0889..6122178f5f8 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -828,12 +828,12 @@ static int dsi_pll_power(enum dsi_pll_power_state state) /* PLL_PWR_STATUS */ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { - udelay(1); - if (t++ > 1000) { + if (++t > 1000) { DSSERR("Failed to set DSI PLL power mode to %d\n", state); return -ENODEV; } + udelay(1); } return 0; @@ -1441,12 +1441,12 @@ static int dsi_complexio_power(enum dsi_complexio_power_state state) /* PWR_STATUS */ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { - udelay(1); - if (t++ > 1000) { + if (++t > 1000) { DSSERR("failed to set complexio power state to " "%d\n", state); return -ENODEV; } + udelay(1); } return 0; @@ -1646,10 +1646,10 @@ static void dsi_complexio_uninit(void) static int _dsi_wait_reset(void) { - int i = 0; + int t = 0; while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { - if (i++ > 5) { + if (++t > 5) { DSSERR("soft reset failed\n"); return -ENODEV; } @@ -2706,7 +2706,6 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, /* using fifo not empty */ /* TX_FIFO_NOT_EMPTY */ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { - udelay(1); fifo_stalls++; if (fifo_stalls > 0xfffff) { DSSERR("fifo stalls overflow, pixels left %d\n", @@ -2714,6 +2713,7 @@ static int dsi_update_screen_l4(struct omap_dss_device *dssdev, dsi_if_enable(0); return -EIO; } + udelay(1); } #elif 1 /* using fifo emptiness */ diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 9b05ee65a15..0a26b7d84d4 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -467,14 +467,14 @@ static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) static int _omap_dss_wait_reset(void) { - unsigned timeout = 1000; + int t = 0; while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { - udelay(1); - if (!--timeout) { + if (++t > 1000) { DSSERR("soft reset failed\n"); return -ENODEV; } + udelay(1); } return 0; -- cgit v1.2.3 From b27d7f16d3c6c27345d4280a739809c1c2c4c0b5 Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Mon, 11 Jan 2010 03:21:50 -0500 Subject: DM: Fix device mapper topology stacking Make DM use bdev_stack_limits() function so that partition offsets get taken into account when calculating alignment. Clarify stacking warnings. Also remove obsolete clearing of final alignment_offset and misalignment flag. Signed-off-by: Martin K. Petersen Signed-off-by: Mike Snitzer Cc: Alasdair G. Kergon Signed-off-by: Jens Axboe --- drivers/md/dm-table.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index be625475cf6..4b22feb01a0 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -503,16 +503,15 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, return 0; } - if (blk_stack_limits(limits, &q->limits, start << 9) < 0) - DMWARN("%s: target device %s is misaligned: " + if (bdev_stack_limits(limits, bdev, start) < 0) + DMWARN("%s: adding target device %s caused an alignment inconsistency: " "physical_block_size=%u, logical_block_size=%u, " "alignment_offset=%u, start=%llu", dm_device_name(ti->table->md), bdevname(bdev, b), q->limits.physical_block_size, q->limits.logical_block_size, q->limits.alignment_offset, - (unsigned long long) start << 9); - + (unsigned long long) start << SECTOR_SHIFT); /* * Check if merge fn is supported. @@ -1026,9 +1025,9 @@ combine_limits: * for the table. */ if (blk_stack_limits(limits, &ti_limits, 0) < 0) - DMWARN("%s: target device " + DMWARN("%s: adding target device " "(start sect %llu len %llu) " - "is misaligned", + "caused an alignment inconsistency", dm_device_name(table->md), (unsigned long long) ti->begin, (unsigned long long) ti->len); @@ -1079,15 +1078,6 @@ no_integrity: void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { - /* - * Each target device in the table has a data area that should normally - * be aligned such that the DM device's alignment_offset is 0. - * FIXME: Propagate alignment_offsets up the stack and warn of - * sub-optimal or inconsistent settings. - */ - limits->alignment_offset = 0; - limits->misaligned = 0; - /* * Copy table's limits to the DM device's request_queue */ -- cgit v1.2.3 From 23978161f90e5a3200ad6ac9b0d534911e4cbb28 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 11 Jan 2010 16:17:12 +0100 Subject: drivers/block/drbd/drbd_receiver.c: correct NULL test Test the just-allocated value for NULL rather than some other value. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,y; statement S; @@ x = \(kmalloc\|kcalloc\|kzalloc\)(...); ( if ((x) == NULL) S | if ( - y + x == NULL) S ) // Signed-off-by: Julia Lawall Cc: Lars Ellenberg Cc: Philipp Reisner Signed-off-by: Andrew Morton Signed-off-by: Jens Axboe --- drivers/block/drbd/drbd_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index a6d266ee7e2..dbd451984e0 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -3945,7 +3945,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) } right_response = kmalloc(resp_size, GFP_NOIO); - if (response == NULL) { + if (right_response == NULL) { dev_err(DEV, "kmalloc of right_response failed\n"); rv = 0; goto fail; -- cgit v1.2.3 From cc20b900be7aa8e456aff82dfcb55fb15c508962 Mon Sep 17 00:00:00 2001 From: Simon Kagstrom Date: Mon, 11 Jan 2010 15:57:24 +0100 Subject: ARM: 5874/1: serial21285: fix disable_irq-from-interrupt-handler deadlock The console hangs during bootup when disable_irq is called from the transmit interrupt handler (it will wait forever for it's "own" interrupt in synchronize_irq). Fix by using disable_irq_nosync() instead. Signed-off-by: Simon Kagstrom Signed-off-by: Russell King --- drivers/serial/21285.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 1e3d19397a5..8681f134505 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -58,7 +58,7 @@ static const char serial21285_name[] = "Footbridge UART"; static void serial21285_stop_tx(struct uart_port *port) { if (tx_enabled(port)) { - disable_irq(IRQ_CONTX); + disable_irq_nosync(IRQ_CONTX); tx_enabled(port) = 0; } } @@ -74,7 +74,7 @@ static void serial21285_start_tx(struct uart_port *port) static void serial21285_stop_rx(struct uart_port *port) { if (rx_enabled(port)) { - disable_irq(IRQ_CONRX); + disable_irq_nosync(IRQ_CONRX); rx_enabled(port) = 0; } } -- cgit v1.2.3 From 0a88422312f5bf7b9e3450e27d8ddc385af38789 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 8 Jan 2010 14:42:57 -0800 Subject: power: fix kernel-doc notation Warning(drivers/base/power/main.c:453): No description found for parameter 'dev' Warning(drivers/base/power/main.c:453): No description found for parameter 'cb' Warning(drivers/base/power/main.c:719): No description found for parameter 'dev' Warning(drivers/base/power/main.c:719): No description found for parameter 'state' Warning(drivers/base/power/main.c:719): No description found for parameter 'cb' Signed-off-by: Randy Dunlap Cc: Rafael J. Wysocki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/power/main.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 48adf80926a..a5142bddef4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -446,8 +446,8 @@ EXPORT_SYMBOL_GPL(dpm_resume_noirq); /** * legacy_resume - Execute a legacy (bus or class) resume callback for device. - * dev: Device to resume. - * cb: Resume callback to execute. + * @dev: Device to resume. + * @cb: Resume callback to execute. */ static int legacy_resume(struct device *dev, int (*cb)(struct device *dev)) { @@ -711,8 +711,9 @@ EXPORT_SYMBOL_GPL(dpm_suspend_noirq); /** * legacy_suspend - Execute a legacy (bus or class) suspend callback for device. - * dev: Device to suspend. - * cb: Suspend callback to execute. + * @dev: Device to suspend. + * @state: PM transition of the system being carried out. + * @cb: Suspend callback to execute. */ static int legacy_suspend(struct device *dev, pm_message_t state, int (*cb)(struct device *dev, pm_message_t state)) -- cgit v1.2.3 From 7d92df692994472cab6045bbd9d0e2c4afa4365f Mon Sep 17 00:00:00 2001 From: Anna Lemehova Date: Fri, 8 Jan 2010 14:42:58 -0800 Subject: mmc_block: add dev_t initialization check When a card is removed before mmc_blk_probe() has called add_disk(), then the minor field is uninitialized and has value 0. This caused mmc_blk_put() to always release devidx 0 even if 0 was still in use. Then the next mmc_blk_probe() used the first free idx of 0, which oopses in sysfs, since it is used by another card. Signed-off-by: Anna Lemehova Signed-off-by: Adrian Hunter Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/card/block.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 85f0e8cd875..5988573bb84 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -85,7 +85,12 @@ static void mmc_blk_put(struct mmc_blk_data *md) mutex_lock(&open_lock); md->usage--; if (md->usage == 0) { + int devmaj = MAJOR(disk_devt(md->disk)); int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; + + if (!devmaj) + devidx = md->disk->first_minor >> MMC_SHIFT; + __clear_bit(devidx, dev_use); put_disk(md->disk); -- cgit v1.2.3 From 0a74ff29b8dd8b748f8856352f9a9b5c6cc362cc Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Fri, 8 Jan 2010 14:42:59 -0800 Subject: mmc_block: fix probe error cleanup bug If mmc_blk_set_blksize() fails mmc_blk_probe() the request queue and its thread have been set up and they need to be shut down properly before putting the disk. Signed-off-by: Jarkko Lavinen Signed-off-by: Adrian Hunter Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/card/block.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 5988573bb84..ee879117017 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -618,6 +618,7 @@ static int mmc_blk_probe(struct mmc_card *card) return 0; out: + mmc_cleanup_queue(&md->queue); mmc_blk_put(md); return err; -- cgit v1.2.3 From 5fa83ce284a4b7cd9dcfadd01500b0ed4ab9b740 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 8 Jan 2010 14:43:00 -0800 Subject: mmc_block: fix queue cleanup The main bug was that 'blk_cleanup_queue()' was called while the block device could still be in use, for example, because the card was removed while files were still open. In addition, to be sure that 'mmc_request()' will get called for all new requests (so it can error them out), the queue is emptied during cleanup. This is done after the worker thread is stopped to avoid racing with it. Finally, it is not a device error for this to be happening, so quiet the (sometimes very many) error messages. Signed-off-by: Adrian Hunter Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/card/block.c | 2 ++ drivers/mmc/card/queue.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index ee879117017..1f552c6e757 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -91,6 +91,8 @@ static void mmc_blk_put(struct mmc_blk_data *md) if (!devmaj) devidx = md->disk->first_minor >> MMC_SHIFT; + blk_cleanup_queue(md->queue.queue); + __clear_bit(devidx, dev_use); put_disk(md->disk); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 49e582356c6..c5a7a855f4b 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -90,9 +90,10 @@ static void mmc_request(struct request_queue *q) struct request *req; if (!mq) { - printk(KERN_ERR "MMC: killing requests for dead queue\n"); - while ((req = blk_fetch_request(q)) != NULL) + while ((req = blk_fetch_request(q)) != NULL) { + req->cmd_flags |= REQ_QUIET; __blk_end_request_all(req, -EIO); + } return; } @@ -223,17 +224,18 @@ void mmc_cleanup_queue(struct mmc_queue *mq) struct request_queue *q = mq->queue; unsigned long flags; - /* Mark that we should start throwing out stragglers */ - spin_lock_irqsave(q->queue_lock, flags); - q->queuedata = NULL; - spin_unlock_irqrestore(q->queue_lock, flags); - /* Make sure the queue isn't suspended, as that will deadlock */ mmc_queue_resume(mq); /* Then terminate our worker thread */ kthread_stop(mq->thread); + /* Empty the queue */ + spin_lock_irqsave(q->queue_lock, flags); + q->queuedata = NULL; + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + if (mq->bounce_sg) kfree(mq->bounce_sg); mq->bounce_sg = NULL; @@ -245,8 +247,6 @@ void mmc_cleanup_queue(struct mmc_queue *mq) kfree(mq->bounce_buf); mq->bounce_buf = NULL; - blk_cleanup_queue(mq->queue); - mq->card = NULL; } EXPORT_SYMBOL(mmc_cleanup_queue); -- cgit v1.2.3 From 11723ab15d28e71dd118a8a92f98493f5a5907da Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 8 Jan 2010 14:43:01 -0800 Subject: mmc: allow for MMC v4.4 JEDEC eMMC specification version 4.4 (MMCA 4.4) defines Extended CSD structure versions up to 5. Signed-off-by: Adrian Hunter Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/core/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index c11189446a1..0eac6c81490 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -207,7 +207,7 @@ static int mmc_read_ext_csd(struct mmc_card *card) } card->ext_csd.rev = ext_csd[EXT_CSD_REV]; - if (card->ext_csd.rev > 3) { + if (card->ext_csd.rev > 5) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), card->ext_csd.rev); -- cgit v1.2.3 From 24f3c59e1781435835083eab587399c8bdc235b4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Jan 2010 14:43:03 -0800 Subject: gpiolib: fix poll(2) support reconfigure on sysfs polarity change Previously enabled poll(2) support on one edge was never reconfigured when sysfs polarity change was triggered from kernel, because 'struct device *dev' shadowed an earlier definition. Found by sparse, which I should've run much earlier. Signed-off-by: Jani Nikula Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/gpiolib.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index a25ad284a27..350842ad363 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -858,8 +858,6 @@ int gpio_sysfs_set_active_low(unsigned gpio, int value) desc = &gpio_desc[gpio]; if (test_bit(FLAG_EXPORT, &desc->flags)) { - struct device *dev; - dev = class_find_device(&gpio_class, NULL, desc, match_export); if (dev == NULL) { status = -ENODEV; -- cgit v1.2.3 From b5430a04e995081a308b4419bd0940f2badc6e6b Mon Sep 17 00:00:00 2001 From: Tomaz Mertelj Date: Fri, 8 Jan 2010 14:43:04 -0800 Subject: hwmon: driver for Texas Instruments amc6821 chip Signed-off-by: Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/amc6821.c | 1116 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1127 insertions(+) create mode 100644 drivers/hwmon/amc6821.c (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 46c3c566307..07a0f030a3e 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -792,6 +792,16 @@ config SENSORS_ADS7828 This driver can also be built as a module. If so, the module will be called ads7828. +config SENSORS_AMC6821 + tristate "Texas Instruments AMC6821" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Texas Instruments + AMC6821 hardware monitoring chips. + + This driver can also be build as a module. If so, the module + will be called amc6821. + config SENSORS_THMC50 tristate "Texas Instruments THMC50 / Analog Devices ADM1022" depends on I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 450c8e89427..4bc215c0953 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -86,6 +86,7 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o +obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o obj-$(CONFIG_SENSORS_THMC50) += thmc50.o obj-$(CONFIG_SENSORS_TMP401) += tmp401.o obj-$(CONFIG_SENSORS_TMP421) += tmp421.o diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c new file mode 100644 index 00000000000..1c89d922d61 --- /dev/null +++ b/drivers/hwmon/amc6821.c @@ -0,0 +1,1116 @@ +/* + amc6821.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (C) 2009 T. Mertelj + + Based on max6650.c: + Copyright (C) 2007 Hans J. Koch + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include /* Needed for KERN_INFO */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Addresses to scan. + */ + +static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, + 0x4c, 0x4d, 0x4e, I2C_CLIENT_END}; + + + +/* + * Insmod parameters + */ + +static int pwminv = 0; /*Inverted PWM output. */ +module_param(pwminv, int, S_IRUGO); + +static int init = 1; /*Power-on initialization.*/ +module_param(init, int, S_IRUGO); + + +enum chips { amc6821 }; + +#define AMC6821_REG_DEV_ID 0x3D +#define AMC6821_REG_COMP_ID 0x3E +#define AMC6821_REG_CONF1 0x00 +#define AMC6821_REG_CONF2 0x01 +#define AMC6821_REG_CONF3 0x3F +#define AMC6821_REG_CONF4 0x04 +#define AMC6821_REG_STAT1 0x02 +#define AMC6821_REG_STAT2 0x03 +#define AMC6821_REG_TDATA_LOW 0x08 +#define AMC6821_REG_TDATA_HI 0x09 +#define AMC6821_REG_LTEMP_HI 0x0A +#define AMC6821_REG_RTEMP_HI 0x0B +#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15 +#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14 +#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19 +#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18 +#define AMC6821_REG_LTEMP_CRIT 0x1B +#define AMC6821_REG_RTEMP_CRIT 0x1D +#define AMC6821_REG_PSV_TEMP 0x1C +#define AMC6821_REG_DCY 0x22 +#define AMC6821_REG_LTEMP_FAN_CTRL 0x24 +#define AMC6821_REG_RTEMP_FAN_CTRL 0x25 +#define AMC6821_REG_DCY_LOW_TEMP 0x21 + +#define AMC6821_REG_TACH_LLIMITL 0x10 +#define AMC6821_REG_TACH_LLIMITH 0x11 +#define AMC6821_REG_TACH_HLIMITL 0x12 +#define AMC6821_REG_TACH_HLIMITH 0x13 + +#define AMC6821_CONF1_START 0x01 +#define AMC6821_CONF1_FAN_INT_EN 0x02 +#define AMC6821_CONF1_FANIE 0x04 +#define AMC6821_CONF1_PWMINV 0x08 +#define AMC6821_CONF1_FAN_FAULT_EN 0x10 +#define AMC6821_CONF1_FDRC0 0x20 +#define AMC6821_CONF1_FDRC1 0x40 +#define AMC6821_CONF1_THERMOVIE 0x80 + +#define AMC6821_CONF2_PWM_EN 0x01 +#define AMC6821_CONF2_TACH_MODE 0x02 +#define AMC6821_CONF2_TACH_EN 0x04 +#define AMC6821_CONF2_RTFIE 0x08 +#define AMC6821_CONF2_LTOIE 0x10 +#define AMC6821_CONF2_RTOIE 0x20 +#define AMC6821_CONF2_PSVIE 0x40 +#define AMC6821_CONF2_RST 0x80 + +#define AMC6821_CONF3_THERM_FAN_EN 0x80 +#define AMC6821_CONF3_REV_MASK 0x0F + +#define AMC6821_CONF4_OVREN 0x10 +#define AMC6821_CONF4_TACH_FAST 0x20 +#define AMC6821_CONF4_PSPR 0x40 +#define AMC6821_CONF4_MODE 0x80 + +#define AMC6821_STAT1_RPM_ALARM 0x01 +#define AMC6821_STAT1_FANS 0x02 +#define AMC6821_STAT1_RTH 0x04 +#define AMC6821_STAT1_RTL 0x08 +#define AMC6821_STAT1_R_THERM 0x10 +#define AMC6821_STAT1_RTF 0x20 +#define AMC6821_STAT1_LTH 0x40 +#define AMC6821_STAT1_LTL 0x80 + +#define AMC6821_STAT2_RTC 0x08 +#define AMC6821_STAT2_LTC 0x10 +#define AMC6821_STAT2_LPSV 0x20 +#define AMC6821_STAT2_L_THERM 0x40 +#define AMC6821_STAT2_THERM_IN 0x80 + +enum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX, + IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN, + IDX_TEMP2_MAX, IDX_TEMP2_CRIT, + TEMP_IDX_LEN, }; + +static const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI, + AMC6821_REG_LTEMP_LIMIT_MIN, + AMC6821_REG_LTEMP_LIMIT_MAX, + AMC6821_REG_LTEMP_CRIT, + AMC6821_REG_RTEMP_HI, + AMC6821_REG_RTEMP_LIMIT_MIN, + AMC6821_REG_RTEMP_LIMIT_MAX, + AMC6821_REG_RTEMP_CRIT, }; + +enum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX, + FAN1_IDX_LEN, }; + +static const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW, + AMC6821_REG_TACH_LLIMITL, + AMC6821_REG_TACH_HLIMITL, }; + + +static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, + AMC6821_REG_TACH_LLIMITH, + AMC6821_REG_TACH_HLIMITH, }; + +static int amc6821_probe( + struct i2c_client *client, + const struct i2c_device_id *id); +static int amc6821_detect( + struct i2c_client *client, + struct i2c_board_info *info); +static int amc6821_init_client(struct i2c_client *client); +static int amc6821_remove(struct i2c_client *client); +static struct amc6821_data *amc6821_update_device(struct device *dev); + +/* + * Driver data (common to all clients) + */ + +static const struct i2c_device_id amc6821_id[] = { + { "amc6821", amc6821 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, amc6821_id); + +static struct i2c_driver amc6821_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "amc6821", + }, + .probe = amc6821_probe, + .remove = amc6821_remove, + .id_table = amc6821_id, + .detect = amc6821_detect, + .address_list = normal_i2c, +}; + + +/* + * Client data (each client gets its own) + */ + +struct amc6821_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* zero until following fields are valid */ + unsigned long last_updated; /* in jiffies */ + + /* register values */ + int temp[TEMP_IDX_LEN]; + + u16 fan[FAN1_IDX_LEN]; + u8 fan1_div; + + u8 pwm1; + u8 temp1_auto_point_temp[3]; + u8 temp2_auto_point_temp[3]; + u8 pwm1_auto_point_pwm[3]; + u8 pwm1_enable; + u8 pwm1_auto_channels_temp; + + u8 stat1; + u8 stat2; +}; + + +static ssize_t get_temp( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + int ix = to_sensor_dev_attr(devattr)->index; + + return sprintf(buf, "%d\n", data->temp[ix] * 1000); +} + + + +static ssize_t set_temp( + struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + int ix = to_sensor_dev_attr(attr)->index; + long val; + + int ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + val = SENSORS_LIMIT(val / 1000, -128, 127); + + mutex_lock(&data->update_lock); + data->temp[ix] = val; + if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) { + dev_err(&client->dev, "Register write error, aborting.\n"); + count = -EIO; + } + mutex_unlock(&data->update_lock); + return count; +} + + + + +static ssize_t get_temp_alarm( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + int ix = to_sensor_dev_attr(devattr)->index; + u8 flag; + + switch (ix) { + case IDX_TEMP1_MIN: + flag = data->stat1 & AMC6821_STAT1_LTL; + break; + case IDX_TEMP1_MAX: + flag = data->stat1 & AMC6821_STAT1_LTH; + break; + case IDX_TEMP1_CRIT: + flag = data->stat2 & AMC6821_STAT2_LTC; + break; + case IDX_TEMP2_MIN: + flag = data->stat1 & AMC6821_STAT1_RTL; + break; + case IDX_TEMP2_MAX: + flag = data->stat1 & AMC6821_STAT1_RTH; + break; + case IDX_TEMP2_CRIT: + flag = data->stat2 & AMC6821_STAT2_RTC; + break; + default: + dev_dbg(dev, "Unknown attr->index (%d).\n", ix); + return -EINVAL; + } + if (flag) + return sprintf(buf, "1"); + else + return sprintf(buf, "0"); +} + + + + +static ssize_t get_temp2_fault( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + if (data->stat1 & AMC6821_STAT1_RTF) + return sprintf(buf, "1"); + else + return sprintf(buf, "0"); +} + +static ssize_t get_pwm1( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + return sprintf(buf, "%d\n", data->pwm1); +} + +static ssize_t set_pwm1( + struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + long val; + int ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->update_lock); + data->pwm1 = SENSORS_LIMIT(val , 0, 255); + i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1); + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t get_pwm1_enable( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + return sprintf(buf, "%d\n", data->pwm1_enable); +} + +static ssize_t set_pwm1_enable( + struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + long val; + int config = strict_strtol(buf, 10, &val); + if (config) + return config; + + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); + return -EIO; + } + + switch (val) { + case 1: + config &= ~AMC6821_CONF1_FDRC0; + config &= ~AMC6821_CONF1_FDRC1; + break; + case 2: + config &= ~AMC6821_CONF1_FDRC0; + config |= AMC6821_CONF1_FDRC1; + break; + case 3: + config |= AMC6821_CONF1_FDRC0; + config |= AMC6821_CONF1_FDRC1; + break; + default: + return -EINVAL; + } + mutex_lock(&data->update_lock); + if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + count = -EIO; + } + mutex_unlock(&data->update_lock); + return count; +} + + +static ssize_t get_pwm1_auto_channels_temp( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp); +} + + +static ssize_t get_temp_auto_point_temp( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int ix = to_sensor_dev_attr_2(devattr)->index; + int nr = to_sensor_dev_attr_2(devattr)->nr; + struct amc6821_data *data = amc6821_update_device(dev); + switch (nr) { + case 1: + return sprintf(buf, "%d\n", + data->temp1_auto_point_temp[ix] * 1000); + break; + case 2: + return sprintf(buf, "%d\n", + data->temp2_auto_point_temp[ix] * 1000); + break; + default: + dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); + return -EINVAL; + } +} + + +static ssize_t get_pwm1_auto_point_pwm( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int ix = to_sensor_dev_attr(devattr)->index; + struct amc6821_data *data = amc6821_update_device(dev); + return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]); +} + + +static inline ssize_t set_slope_register(struct i2c_client *client, + u8 reg, + u8 dpwm, + u8 *ptemp) +{ + int dt; + u8 tmp; + + dt = ptemp[2]-ptemp[1]; + for (tmp = 4; tmp > 0; tmp--) { + if (dt * (0x20 >> tmp) >= dpwm) + break; + } + tmp |= (ptemp[1] & 0x7C) << 1; + if (i2c_smbus_write_byte_data(client, + reg, tmp)) { + dev_err(&client->dev, "Register write error, aborting.\n"); + return -EIO; + } + return 0; +} + + + +static ssize_t set_temp_auto_point_temp( + struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = amc6821_update_device(dev); + int ix = to_sensor_dev_attr_2(attr)->index; + int nr = to_sensor_dev_attr_2(attr)->nr; + u8 *ptemp; + u8 reg; + int dpwm; + long val; + int ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + switch (nr) { + case 1: + ptemp = data->temp1_auto_point_temp; + reg = AMC6821_REG_LTEMP_FAN_CTRL; + break; + case 2: + ptemp = data->temp2_auto_point_temp; + reg = AMC6821_REG_RTEMP_FAN_CTRL; + break; + default: + dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); + return -EINVAL; + } + + data->valid = 0; + mutex_lock(&data->update_lock); + switch (ix) { + case 0: + ptemp[0] = SENSORS_LIMIT(val / 1000, 0, + data->temp1_auto_point_temp[1]); + ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, + data->temp2_auto_point_temp[1]); + ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63); + if (i2c_smbus_write_byte_data( + client, + AMC6821_REG_PSV_TEMP, + ptemp[0])) { + dev_err(&client->dev, + "Register write error, aborting.\n"); + count = -EIO; + } + goto EXIT; + break; + case 1: + ptemp[1] = SENSORS_LIMIT( + val / 1000, + (ptemp[0] & 0x7C) + 4, + 124); + ptemp[1] &= 0x7C; + ptemp[2] = SENSORS_LIMIT( + ptemp[2], ptemp[1] + 1, + 255); + break; + case 2: + ptemp[2] = SENSORS_LIMIT( + val / 1000, + ptemp[1]+1, + 255); + break; + default: + dev_dbg(dev, "Unknown attr->index (%d).\n", ix); + count = -EINVAL; + goto EXIT; + } + dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; + if (set_slope_register(client, reg, dpwm, ptemp)) + count = -EIO; + +EXIT: + mutex_unlock(&data->update_lock); + return count; +} + + + +static ssize_t set_pwm1_auto_point_pwm( + struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + int dpwm; + long val; + int ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + + mutex_lock(&data->update_lock); + data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254); + if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP, + data->pwm1_auto_point_pwm[1])) { + dev_err(&client->dev, "Register write error, aborting.\n"); + count = -EIO; + goto EXIT; + } + dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; + if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm, + data->temp1_auto_point_temp)) { + count = -EIO; + goto EXIT; + } + if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm, + data->temp2_auto_point_temp)) { + count = -EIO; + goto EXIT; + } + +EXIT: + data->valid = 0; + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t get_fan( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + int ix = to_sensor_dev_attr(devattr)->index; + if (0 == data->fan[ix]) + return sprintf(buf, "0"); + return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix])); +} + + + +static ssize_t get_fan1_fault( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + if (data->stat1 & AMC6821_STAT1_FANS) + return sprintf(buf, "1"); + else + return sprintf(buf, "0"); +} + + + +static ssize_t set_fan( + struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + long val; + int ix = to_sensor_dev_attr(attr)->index; + int ret = strict_strtol(buf, 10, &val); + if (ret) + return ret; + val = 1 > val ? 0xFFFF : 6000000/val; + + mutex_lock(&data->update_lock); + data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF); + if (i2c_smbus_write_byte_data(client, fan_reg_low[ix], + data->fan[ix] & 0xFF)) { + dev_err(&client->dev, "Register write error, aborting.\n"); + count = -EIO; + goto EXIT; + } + if (i2c_smbus_write_byte_data(client, + fan_reg_hi[ix], data->fan[ix] >> 8)) { + dev_err(&client->dev, "Register write error, aborting.\n"); + count = -EIO; + } +EXIT: + mutex_unlock(&data->update_lock); + return count; +} + + + +static ssize_t get_fan1_div( + struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct amc6821_data *data = amc6821_update_device(dev); + return sprintf(buf, "%d\n", data->fan1_div); +} + +static ssize_t set_fan1_div( + struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + long val; + int config = strict_strtol(buf, 10, &val); + if (config) + return config; + + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); + return -EIO; + } + mutex_lock(&data->update_lock); + switch (val) { + case 2: + config &= ~AMC6821_CONF4_PSPR; + data->fan1_div = 2; + break; + case 4: + config |= AMC6821_CONF4_PSPR; + data->fan1_div = 4; + break; + default: + mutex_unlock(&data->update_lock); + count = -EINVAL; + goto EXIT; + } + if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + count = -EIO; + } +EXIT: + mutex_unlock(&data->update_lock); + return count; +} + + + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, + get_temp, NULL, IDX_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp, + set_temp, IDX_TEMP1_MIN); +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp, + set_temp, IDX_TEMP1_MAX); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp, + set_temp, IDX_TEMP1_CRIT); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, + get_temp_alarm, NULL, IDX_TEMP1_MIN); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, + get_temp_alarm, NULL, IDX_TEMP1_MAX); +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, + get_temp_alarm, NULL, IDX_TEMP1_CRIT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO | S_IWUSR, + get_temp, NULL, IDX_TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp, + set_temp, IDX_TEMP2_MIN); +static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp, + set_temp, IDX_TEMP2_MAX); +static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp, + set_temp, IDX_TEMP2_CRIT); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, + get_temp2_fault, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, + get_temp_alarm, NULL, IDX_TEMP2_MIN); +static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, + get_temp_alarm, NULL, IDX_TEMP2_MAX); +static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, + get_temp_alarm, NULL, IDX_TEMP2_CRIT); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT); +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, + get_fan, set_fan, IDX_FAN1_MIN); +static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR, + get_fan, set_fan, IDX_FAN1_MAX); +static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, + get_fan1_div, set_fan1_div, 0); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0); +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, + get_pwm1_enable, set_pwm1_enable, 0); +static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, + get_pwm1_auto_point_pwm, NULL, 0); +static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, + get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, + get_pwm1_auto_point_pwm, NULL, 2); +static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO, + get_pwm1_auto_channels_temp, NULL, 0); +static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO, + get_temp_auto_point_temp, NULL, 1, 0); +static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, + get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1); +static SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO, + get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2); + +static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, + get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0); +static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, + get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1); +static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO, + get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2); + + + +static struct attribute *amc6821_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan1_fault.dev_attr.attr, + &sensor_dev_attr_fan1_div.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, + &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr, + NULL +}; + +static struct attribute_group amc6821_attr_grp = { + .attrs = amc6821_attrs, +}; + + + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int amc6821_detect( + struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int address = client->addr; + int dev_id, comp_id; + + dev_dbg(&adapter->dev, "amc6821_detect called.\n"); + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_dbg(&adapter->dev, + "amc6821: I2C bus doesn't support byte mode, " + "skipping.\n"); + return -ENODEV; + } + + dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID); + comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID); + if (dev_id != 0x21 || comp_id != 0x49) { + dev_dbg(&adapter->dev, + "amc6821: detection failed at 0x%02x.\n", + address); + return -ENODEV; + } + + /* Bit 7 of the address register is ignored, so we can check the + ID registers again */ + dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID); + comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID); + if (dev_id != 0x21 || comp_id != 0x49) { + dev_dbg(&adapter->dev, + "amc6821: detection failed at 0x%02x.\n", + address); + return -ENODEV; + } + + dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address); + strlcpy(info->type, "amc6821", I2C_NAME_SIZE); + + return 0; +} + +static int amc6821_probe( + struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct amc6821_data *data; + int err; + + data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL); + if (!data) { + dev_err(&client->dev, "out of memory.\n"); + return -ENOMEM; + } + + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* + * Initialize the amc6821 chip + */ + err = amc6821_init_client(client); + if (err) + goto err_free; + + err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); + if (err) + goto err_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (!IS_ERR(data->hwmon_dev)) + return 0; + + err = PTR_ERR(data->hwmon_dev); + dev_err(&client->dev, "error registering hwmon device.\n"); + sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); +err_free: + kfree(data); + return err; +} + +static int amc6821_remove(struct i2c_client *client) +{ + struct amc6821_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); + + kfree(data); + + return 0; +} + + +static int amc6821_init_client(struct i2c_client *client) +{ + int config; + int err = -EIO; + + if (init) { + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); + + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); + return err; + } + + config |= AMC6821_CONF4_MODE; + + if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, + config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + return err; + } + + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3); + + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); + return err; + } + + dev_info(&client->dev, "Revision %d\n", config & 0x0f); + + config &= ~AMC6821_CONF3_THERM_FAN_EN; + + if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3, + config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + return err; + } + + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2); + + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); + return err; + } + + config &= ~AMC6821_CONF2_RTFIE; + config &= ~AMC6821_CONF2_LTOIE; + config &= ~AMC6821_CONF2_RTOIE; + if (i2c_smbus_write_byte_data(client, + AMC6821_REG_CONF2, config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + return err; + } + + config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); + + if (config < 0) { + dev_err(&client->dev, + "Error reading configuration register, aborting.\n"); + return err; + } + + config &= ~AMC6821_CONF1_THERMOVIE; + config &= ~AMC6821_CONF1_FANIE; + config |= AMC6821_CONF1_START; + if (pwminv) + config |= AMC6821_CONF1_PWMINV; + else + config &= ~AMC6821_CONF1_PWMINV; + + if (i2c_smbus_write_byte_data( + client, AMC6821_REG_CONF1, config)) { + dev_err(&client->dev, + "Configuration register write error, aborting.\n"); + return err; + } + } + return 0; +} + + +static struct amc6821_data *amc6821_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct amc6821_data *data = i2c_get_clientdata(client); + int timeout = HZ; + u8 reg; + int i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + timeout) || + !data->valid) { + + for (i = 0; i < TEMP_IDX_LEN; i++) + data->temp[i] = i2c_smbus_read_byte_data(client, + temp_reg[i]); + + data->stat1 = i2c_smbus_read_byte_data(client, + AMC6821_REG_STAT1); + data->stat2 = i2c_smbus_read_byte_data(client, + AMC6821_REG_STAT2); + + data->pwm1 = i2c_smbus_read_byte_data(client, + AMC6821_REG_DCY); + for (i = 0; i < FAN1_IDX_LEN; i++) { + data->fan[i] = i2c_smbus_read_byte_data( + client, + fan_reg_low[i]); + data->fan[i] += i2c_smbus_read_byte_data( + client, + fan_reg_hi[i]) << 8; + } + data->fan1_div = i2c_smbus_read_byte_data(client, + AMC6821_REG_CONF4); + data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; + + data->pwm1_auto_point_pwm[0] = 0; + data->pwm1_auto_point_pwm[2] = 255; + data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, + AMC6821_REG_DCY_LOW_TEMP); + + data->temp1_auto_point_temp[0] = + i2c_smbus_read_byte_data(client, + AMC6821_REG_PSV_TEMP); + data->temp2_auto_point_temp[0] = + data->temp1_auto_point_temp[0]; + reg = i2c_smbus_read_byte_data(client, + AMC6821_REG_LTEMP_FAN_CTRL); + data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; + reg &= 0x07; + reg = 0x20 >> reg; + if (reg > 0) + data->temp1_auto_point_temp[2] = + data->temp1_auto_point_temp[1] + + (data->pwm1_auto_point_pwm[2] - + data->pwm1_auto_point_pwm[1]) / reg; + else + data->temp1_auto_point_temp[2] = 255; + + reg = i2c_smbus_read_byte_data(client, + AMC6821_REG_RTEMP_FAN_CTRL); + data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; + reg &= 0x07; + reg = 0x20 >> reg; + if (reg > 0) + data->temp2_auto_point_temp[2] = + data->temp2_auto_point_temp[1] + + (data->pwm1_auto_point_pwm[2] - + data->pwm1_auto_point_pwm[1]) / reg; + else + data->temp2_auto_point_temp[2] = 255; + + reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); + reg = (reg >> 5) & 0x3; + switch (reg) { + case 0: /*open loop: software sets pwm1*/ + data->pwm1_auto_channels_temp = 0; + data->pwm1_enable = 1; + break; + case 2: /*closed loop: remote T (temp2)*/ + data->pwm1_auto_channels_temp = 2; + data->pwm1_enable = 2; + break; + case 3: /*closed loop: local and remote T (temp2)*/ + data->pwm1_auto_channels_temp = 3; + data->pwm1_enable = 3; + break; + case 1: /*semi-open loop: software sets rpm, chip controls pwm1, + *currently not implemented + */ + data->pwm1_auto_channels_temp = 0; + data->pwm1_enable = 0; + break; + } + + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + + +static int __init amc6821_init(void) +{ + return i2c_add_driver(&amc6821_driver); +} + +static void __exit amc6821_exit(void) +{ + i2c_del_driver(&amc6821_driver); +} + +module_init(amc6821_init); +module_exit(amc6821_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("T. Mertelj "); +MODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver"); -- cgit v1.2.3 From 5787536edf18e33d06e2bf038bfd0910f4def213 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 8 Jan 2010 14:43:08 -0800 Subject: drivers/cpuidle/governors/menu.c: fix undefined reference to `__udivdi3' menu: use proper 64 bit math The new menu governor is incorrectly doing a 64 bit divide. Compile tested only Signed-off-by: Stephen Hemminger Cc: Arjan van de Ven Cc: Len Brown Cc: Venkatesh Pallipadi Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpuidle/governors/menu.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 68104434ebb..73655aeb3a6 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -18,6 +18,7 @@ #include #include #include +#include #define BUCKETS 12 #define RESOLUTION 1024 @@ -169,6 +170,12 @@ static DEFINE_PER_CPU(struct menu_device, menu_devices); static void menu_update(struct cpuidle_device *dev); +/* This implements DIV_ROUND_CLOSEST but avoids 64 bit division */ +static u64 div_round64(u64 dividend, u32 divisor) +{ + return div_u64(dividend + (divisor / 2), divisor); +} + /** * menu_select - selects the next idle state to enter * @dev: the CPU @@ -209,9 +216,8 @@ static int menu_select(struct cpuidle_device *dev) data->correction_factor[data->bucket] = RESOLUTION * DECAY; /* Make sure to round up for half microseconds */ - data->predicted_us = DIV_ROUND_CLOSEST( - data->expected_us * data->correction_factor[data->bucket], - RESOLUTION * DECAY); + data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], + RESOLUTION * DECAY); /* * We want to default to C1 (hlt), not to busy polling -- cgit v1.2.3 From 80884094e34456887ecdbd107d40e72c4a40f9c9 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 8 Jan 2010 14:43:08 -0800 Subject: gpio: adp5588-gpio: new driver for ADP5588 GPIO expanders Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Cc: Jean Delvare Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/Kconfig | 9 ++ drivers/gpio/Makefile | 1 + drivers/gpio/adp5588-gpio.c | 266 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 drivers/gpio/adp5588-gpio.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a019b49ecc9..1f1d88ae68d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -172,6 +172,15 @@ config GPIO_ADP5520 To compile this driver as a module, choose M here: the module will be called adp5520-gpio. +config GPIO_ADP5588 + tristate "ADP5588 I2C GPIO expander" + depends on I2C + help + This option enables support for 18 GPIOs found + on Analog Devices ADP5588 GPIO Expanders. + To compile this driver as a module, choose M here: the module will be + called adp5588-gpio. + comment "PCI GPIO expanders:" config GPIO_CS5535 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 52fe4cf734c..48687238edb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o +obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o obj-$(CONFIG_GPIO_MAX7301) += max7301.o obj-$(CONFIG_GPIO_MAX732X) += max732x.o diff --git a/drivers/gpio/adp5588-gpio.c b/drivers/gpio/adp5588-gpio.c new file mode 100644 index 00000000000..afc097a16b3 --- /dev/null +++ b/drivers/gpio/adp5588-gpio.c @@ -0,0 +1,266 @@ +/* + * GPIO Chip driver for Analog Devices + * ADP5588 I/O Expander and QWERTY Keypad Controller + * + * Copyright 2009 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include + +#include + +#define DRV_NAME "adp5588-gpio" +#define MAXGPIO 18 +#define ADP_BANK(offs) ((offs) >> 3) +#define ADP_BIT(offs) (1u << ((offs) & 0x7)) + +struct adp5588_gpio { + struct i2c_client *client; + struct gpio_chip gpio_chip; + struct mutex lock; /* protect cached dir, dat_out */ + unsigned gpio_start; + uint8_t dat_out[3]; + uint8_t dir[3]; +}; + +static int adp5588_gpio_read(struct i2c_client *client, u8 reg) +{ + int ret = i2c_smbus_read_byte_data(client, reg); + + if (ret < 0) + dev_err(&client->dev, "Read Error\n"); + + return ret; +} + +static int adp5588_gpio_write(struct i2c_client *client, u8 reg, u8 val) +{ + int ret = i2c_smbus_write_byte_data(client, reg, val); + + if (ret < 0) + dev_err(&client->dev, "Write Error\n"); + + return ret; +} + +static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off) +{ + struct adp5588_gpio *dev = + container_of(chip, struct adp5588_gpio, gpio_chip); + + return !!(adp5588_gpio_read(dev->client, GPIO_DAT_STAT1 + ADP_BANK(off)) + & ADP_BIT(off)); +} + +static void adp5588_gpio_set_value(struct gpio_chip *chip, + unsigned off, int val) +{ + unsigned bank, bit; + struct adp5588_gpio *dev = + container_of(chip, struct adp5588_gpio, gpio_chip); + + bank = ADP_BANK(off); + bit = ADP_BIT(off); + + mutex_lock(&dev->lock); + if (val) + dev->dat_out[bank] |= bit; + else + dev->dat_out[bank] &= ~bit; + + adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank, + dev->dat_out[bank]); + mutex_unlock(&dev->lock); +} + +static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off) +{ + int ret; + unsigned bank; + struct adp5588_gpio *dev = + container_of(chip, struct adp5588_gpio, gpio_chip); + + bank = ADP_BANK(off); + + mutex_lock(&dev->lock); + dev->dir[bank] &= ~ADP_BIT(off); + ret = adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, dev->dir[bank]); + mutex_unlock(&dev->lock); + + return ret; +} + +static int adp5588_gpio_direction_output(struct gpio_chip *chip, + unsigned off, int val) +{ + int ret; + unsigned bank, bit; + struct adp5588_gpio *dev = + container_of(chip, struct adp5588_gpio, gpio_chip); + + bank = ADP_BANK(off); + bit = ADP_BIT(off); + + mutex_lock(&dev->lock); + dev->dir[bank] |= bit; + + if (val) + dev->dat_out[bank] |= bit; + else + dev->dat_out[bank] &= ~bit; + + ret = adp5588_gpio_write(dev->client, GPIO_DAT_OUT1 + bank, + dev->dat_out[bank]); + ret |= adp5588_gpio_write(dev->client, GPIO_DIR1 + bank, + dev->dir[bank]); + mutex_unlock(&dev->lock); + + return ret; +} + +static int __devinit adp5588_gpio_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adp5588_gpio_platform_data *pdata = client->dev.platform_data; + struct adp5588_gpio *dev; + struct gpio_chip *gc; + int ret, i, revid; + + if (pdata == NULL) { + dev_err(&client->dev, "missing platform data\n"); + return -ENODEV; + } + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); + return -EIO; + } + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&client->dev, "failed to alloc memory\n"); + return -ENOMEM; + } + + dev->client = client; + + gc = &dev->gpio_chip; + gc->direction_input = adp5588_gpio_direction_input; + gc->direction_output = adp5588_gpio_direction_output; + gc->get = adp5588_gpio_get_value; + gc->set = adp5588_gpio_set_value; + gc->can_sleep = 1; + + gc->base = pdata->gpio_start; + gc->ngpio = MAXGPIO; + gc->label = client->name; + gc->owner = THIS_MODULE; + + mutex_init(&dev->lock); + + + ret = adp5588_gpio_read(dev->client, DEV_ID); + if (ret < 0) + goto err; + + revid = ret & ADP5588_DEVICE_ID_MASK; + + for (i = 0, ret = 0; i <= ADP_BANK(MAXGPIO); i++) { + dev->dat_out[i] = adp5588_gpio_read(client, GPIO_DAT_OUT1 + i); + dev->dir[i] = adp5588_gpio_read(client, GPIO_DIR1 + i); + ret |= adp5588_gpio_write(client, KP_GPIO1 + i, 0); + ret |= adp5588_gpio_write(client, GPIO_PULL1 + i, + (pdata->pullup_dis_mask >> (8 * i)) & 0xFF); + + if (ret) + goto err; + } + + ret = gpiochip_add(&dev->gpio_chip); + if (ret) + goto err; + + dev_info(&client->dev, "gpios %d..%d on a %s Rev. %d\n", + gc->base, gc->base + gc->ngpio - 1, + client->name, revid); + + if (pdata->setup) { + ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context); + if (ret < 0) + dev_warn(&client->dev, "setup failed, %d\n", ret); + } + + i2c_set_clientdata(client, dev); + return 0; + +err: + kfree(dev); + return ret; +} + +static int __devexit adp5588_gpio_remove(struct i2c_client *client) +{ + struct adp5588_gpio_platform_data *pdata = client->dev.platform_data; + struct adp5588_gpio *dev = i2c_get_clientdata(client); + int ret; + + if (pdata->teardown) { + ret = pdata->teardown(client, + dev->gpio_chip.base, dev->gpio_chip.ngpio, + pdata->context); + if (ret < 0) { + dev_err(&client->dev, "teardown failed %d\n", ret); + return ret; + } + } + + ret = gpiochip_remove(&dev->gpio_chip); + if (ret) { + dev_err(&client->dev, "gpiochip_remove failed %d\n", ret); + return ret; + } + + kfree(dev); + return 0; +} + +static const struct i2c_device_id adp5588_gpio_id[] = { + {DRV_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, adp5588_gpio_id); + +static struct i2c_driver adp5588_gpio_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = adp5588_gpio_probe, + .remove = __devexit_p(adp5588_gpio_remove), + .id_table = adp5588_gpio_id, +}; + +static int __init adp5588_gpio_init(void) +{ + return i2c_add_driver(&adp5588_gpio_driver); +} + +module_init(adp5588_gpio_init); + +static void __exit adp5588_gpio_exit(void) +{ + i2c_del_driver(&adp5588_gpio_driver); +} + +module_exit(adp5588_gpio_exit); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("GPIO ADP5588 Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 004731b2c7c658d36bee167cb1e1a399c2cbccc9 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Fri, 8 Jan 2010 14:43:11 -0800 Subject: rtc_cmos: convert shutdown to new pnp_driver->shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit abd6633c67925f90775bb74755f9c547e30f1f20 ("pnp: add a shutdown method to pnp drivers") adds shutdown method to bus driver blindly. With it, driver->shutdown is no longer valid. Use pnp_driver->shutdown instead. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14889 Signed-off-by: OGAWA Hirofumi Reported-by: Malte Schröder Cc: "Rafael J. Wysocki" Cc: Bjorn Helgaas Cc: David Hardeman Cc: Dmitry Torokhov Cc: Alessandro Zummo Cc: Paul Gortmaker Cc: [2.6.32.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-cmos.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index c8c12325e69..e9aa814ddd2 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -1096,9 +1096,9 @@ static int cmos_pnp_resume(struct pnp_dev *pnp) #define cmos_pnp_resume NULL #endif -static void cmos_pnp_shutdown(struct device *pdev) +static void cmos_pnp_shutdown(struct pnp_dev *pnp) { - if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(pdev)) + if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev)) return; cmos_do_shutdown(); @@ -1117,15 +1117,12 @@ static struct pnp_driver cmos_pnp_driver = { .id_table = rtc_ids, .probe = cmos_pnp_probe, .remove = __exit_p(cmos_pnp_remove), + .shutdown = cmos_pnp_shutdown, /* flag ensures resume() gets called, and stops syslog spam */ .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, .suspend = cmos_pnp_suspend, .resume = cmos_pnp_resume, - .driver = { - .name = (char *)driver_name, - .shutdown = cmos_pnp_shutdown, - } }; #endif /* CONFIG_PNP */ -- cgit v1.2.3 From 39825f4dc9f4e409e8ea43ef4df04a924699ad1f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 9 Jan 2010 11:41:48 +0300 Subject: iwlwifi: silence buffer overflow warning Smatch (and presumably other static checkers) complain that MAX_TID_COUNT is past the end of the array. In the resulting discussion, Zhu Yi pointed out that this value is not used in real life and the assignment was only there to silence a gcc warning. If there were a bug in the surrounding code and the value were used, the WARN_ON(!qc) would print a warning before the crash. Signed-off-by: Dan Carpenter Acked-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 761aab127e7..9b4b8b5c757 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1961,7 +1961,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct ieee80211_tx_info *info; struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->u.status); - int tid = MAX_TID_COUNT - 1; + int uninitialized_var(tid); int sta_id; int freed; u8 *qc = NULL; -- cgit v1.2.3 From b10d96cb9c9a2a0029d28910ca517f4003051b04 Mon Sep 17 00:00:00 2001 From: Johannes Thoma Date: Thu, 7 Jan 2010 16:02:50 +0100 Subject: drbd: Don't go into StandAlone mode when authentification failes because of network error Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_receiver.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index dbd451984e0..e3716fadc6a 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -878,9 +878,13 @@ retry: if (mdev->cram_hmac_tfm) { /* drbd_request_state(mdev, NS(conn, WFAuth)); */ - if (!drbd_do_auth(mdev)) { + switch (drbd_do_auth(mdev)) { + case -1: dev_err(DEV, "Authentication of peer failed\n"); return -1; + case 0: + dev_err(DEV, "Authentication of peer failed, trying again.\n"); + return 0; } } @@ -3831,10 +3835,17 @@ static int drbd_do_auth(struct drbd_conf *mdev) { dev_err(DEV, "This kernel was build without CONFIG_CRYPTO_HMAC.\n"); dev_err(DEV, "You need to disable 'cram-hmac-alg' in drbd.conf.\n"); - return 0; + return -1; } #else #define CHALLENGE_LEN 64 + +/* Return value: + 1 - auth succeeded, + 0 - failed, try again (network error), + -1 - auth failed, don't try again. +*/ + static int drbd_do_auth(struct drbd_conf *mdev) { char my_challenge[CHALLENGE_LEN]; /* 64 Bytes... */ @@ -3855,7 +3866,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) (u8 *)mdev->net_conf->shared_secret, key_len); if (rv) { dev_err(DEV, "crypto_hash_setkey() failed with %d\n", rv); - rv = 0; + rv = -1; goto fail; } @@ -3878,14 +3889,14 @@ static int drbd_do_auth(struct drbd_conf *mdev) if (p.length > CHALLENGE_LEN*2) { dev_err(DEV, "expected AuthChallenge payload too big.\n"); - rv = 0; + rv = -1; goto fail; } peers_ch = kmalloc(p.length, GFP_NOIO); if (peers_ch == NULL) { dev_err(DEV, "kmalloc of peers_ch failed\n"); - rv = 0; + rv = -1; goto fail; } @@ -3901,7 +3912,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) response = kmalloc(resp_size, GFP_NOIO); if (response == NULL) { dev_err(DEV, "kmalloc of response failed\n"); - rv = 0; + rv = -1; goto fail; } @@ -3911,7 +3922,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) rv = crypto_hash_digest(&desc, &sg, sg.length, response); if (rv) { dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv); - rv = 0; + rv = -1; goto fail; } @@ -3947,7 +3958,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) right_response = kmalloc(resp_size, GFP_NOIO); if (right_response == NULL) { dev_err(DEV, "kmalloc of right_response failed\n"); - rv = 0; + rv = -1; goto fail; } @@ -3956,7 +3967,7 @@ static int drbd_do_auth(struct drbd_conf *mdev) rv = crypto_hash_digest(&desc, &sg, sg.length, right_response); if (rv) { dev_err(DEV, "crypto_hash_digest() failed with %d\n", rv); - rv = 0; + rv = -1; goto fail; } @@ -3965,6 +3976,8 @@ static int drbd_do_auth(struct drbd_conf *mdev) if (rv) dev_info(DEV, "Peer authenticated using %d bytes of '%s' HMAC\n", resp_size, mdev->net_conf->cram_hmac_alg); + else + rv = -1; fail: kfree(peers_ch); -- cgit v1.2.3 From a393db6f10ef2d4f28257234cfc730e744dfb6a4 Mon Sep 17 00:00:00 2001 From: Philipp Reisner Date: Tue, 22 Dec 2009 13:35:52 +0100 Subject: drbd: Allow online resizing of DRBD devices while peer not reachable (needs to be explicitly forced) Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- drivers/block/drbd/drbd_int.h | 5 ++--- drivers/block/drbd/drbd_nl.c | 17 +++++++++++------ drivers/block/drbd/drbd_receiver.c | 4 ++-- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 79d8e22c4d0..2bf3a6ef368 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1371,10 +1371,9 @@ extern int is_valid_ar_handle(struct drbd_request *, sector_t); extern void drbd_suspend_io(struct drbd_conf *mdev); extern void drbd_resume_io(struct drbd_conf *mdev); extern char *ppsize(char *buf, unsigned long long size); -extern sector_t drbd_new_dev_size(struct drbd_conf *, - struct drbd_backing_dev *); +extern sector_t drbd_new_dev_size(struct drbd_conf *, struct drbd_backing_dev *, int); enum determine_dev_size { dev_size_error = -1, unchanged = 0, shrunk = 1, grew = 2 }; -extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *) __must_hold(local); +extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, int force) __must_hold(local); extern void resync_after_online_grow(struct drbd_conf *); extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local); extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 3313901a486..1292e062066 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -510,7 +510,7 @@ void drbd_resume_io(struct drbd_conf *mdev) * Returns 0 on success, negative return values indicate errors. * You should call drbd_md_sync() after calling this function. */ -enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_hold(local) +enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev, int force) __must_hold(local) { sector_t prev_first_sect, prev_size; /* previous meta location */ sector_t la_size; @@ -541,7 +541,7 @@ enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *mdev) __must_ho /* TODO: should only be some assert here, not (re)init... */ drbd_md_set_sector_offsets(mdev, mdev->ldev); - size = drbd_new_dev_size(mdev, mdev->ldev); + size = drbd_new_dev_size(mdev, mdev->ldev, force); if (drbd_get_capacity(mdev->this_bdev) != size || drbd_bm_capacity(mdev) != size) { @@ -596,7 +596,7 @@ out: } sector_t -drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) +drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev, int assume_peer_has_space) { sector_t p_size = mdev->p_size; /* partner's disk size. */ sector_t la_size = bdev->md.la_size_sect; /* last agreed size. */ @@ -606,6 +606,11 @@ drbd_new_dev_size(struct drbd_conf *mdev, struct drbd_backing_dev *bdev) m_size = drbd_get_max_capacity(bdev); + if (mdev->state.conn < C_CONNECTED && assume_peer_has_space) { + dev_warn(DEV, "Resize while not connected was forced by the user!\n"); + p_size = m_size; + } + if (p_size && m_size) { size = min_t(sector_t, p_size, m_size); } else { @@ -965,7 +970,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp /* Prevent shrinking of consistent devices ! */ if (drbd_md_test_flag(nbc, MDF_CONSISTENT) && - drbd_new_dev_size(mdev, nbc) < nbc->md.la_size_sect) { + drbd_new_dev_size(mdev, nbc, 0) < nbc->md.la_size_sect) { dev_warn(DEV, "refusing to truncate a consistent device\n"); retcode = ERR_DISK_TO_SMALL; goto force_diskless_dec; @@ -1052,7 +1057,7 @@ static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp !drbd_md_test_flag(mdev->ldev, MDF_CONNECTED_IND)) set_bit(USE_DEGR_WFC_T, &mdev->flags); - dd = drbd_determin_dev_size(mdev); + dd = drbd_determin_dev_size(mdev, 0); if (dd == dev_size_error) { retcode = ERR_NOMEM_BITMAP; goto force_diskless_dec; @@ -1504,7 +1509,7 @@ static int drbd_nl_resize(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp, } mdev->ldev->dc.disk_size = (sector_t)rs.resize_size; - dd = drbd_determin_dev_size(mdev); + dd = drbd_determin_dev_size(mdev, rs.resize_force); drbd_md_sync(mdev); put_ldev(mdev); if (dd == dev_size_error) { diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index e3716fadc6a..f22a5283128 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2870,7 +2870,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h) /* Never shrink a device with usable data during connect. But allow online shrinking if we are connected. */ - if (drbd_new_dev_size(mdev, mdev->ldev) < + if (drbd_new_dev_size(mdev, mdev->ldev, 0) < drbd_get_capacity(mdev->this_bdev) && mdev->state.disk >= D_OUTDATED && mdev->state.conn < C_CONNECTED) { @@ -2885,7 +2885,7 @@ static int receive_sizes(struct drbd_conf *mdev, struct p_header *h) #undef min_not_zero if (get_ldev(mdev)) { - dd = drbd_determin_dev_size(mdev); + dd = drbd_determin_dev_size(mdev, 0); put_ldev(mdev); if (dd == dev_size_error) return FALSE; -- cgit v1.2.3 From 2d9c5597ad1408885fdef5838aa27a8a0ee9e915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 8 Jan 2010 11:56:41 +0200 Subject: OMAP: DSS2: Reject scaling settings when they cannot be supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the scaling ratio is below 0.5 video output width can't be identical to the display width. Reject such settings. Signed-off-by: Ville Syrjälä Acked-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index e2e0f9ae735..de8bfbac9e2 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1454,7 +1454,10 @@ static unsigned long calc_fclk_five_taps(u16 width, u16 height, do_div(tmp, 2 * out_height * ppl); fclk = tmp; - if (height > 2 * out_height && ppl != out_width) { + if (height > 2 * out_height) { + if (ppl == out_width) + return 0; + tmp = pclk * (height - 2 * out_height) * out_width; do_div(tmp, 2 * out_height * (ppl - out_width)); fclk = max(fclk, (u32) tmp); @@ -1634,7 +1637,7 @@ static int _dispc_setup_plane(enum omap_plane plane, DSSDBG("required fclk rate = %lu Hz\n", fclk); DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); - if (fclk > dispc_fclk_rate()) { + if (!fclk || fclk > dispc_fclk_rate()) { DSSERR("failed to set up scaling, " "required fclk rate = %lu Hz, " "current fclk rate = %lu Hz\n", -- cgit v1.2.3 From 807a7515aea421f2b340140482ed4c8811c523c6 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 7 Jan 2010 17:45:03 +0200 Subject: OMAP: DSS2: OMAPFB: fix crash when panel driver was not loaded If the panel's probe had failed, omapfb would still go on, eventually crashing. A better fix would be to handle each display properly, and leaving just the failed display out. But that is a bigger change. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/omapfb/omapfb-main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index e61a75c3135..d17caef6915 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -2115,6 +2115,11 @@ static int omapfb_probe(struct platform_device *pdev) dssdev = NULL; for_each_dss_dev(dssdev) { omap_dss_get_device(dssdev); + if (!dssdev->driver) { + dev_err(&pdev->dev, "no driver for display\n"); + r = -EINVAL; + goto cleanup; + } fbdev->displays[fbdev->num_displays++] = dssdev; } -- cgit v1.2.3 From 9db2f1bec36805e57a003f7bb90e003815d96de8 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 4 Jan 2010 08:48:41 +0000 Subject: sky2: Fix oops in sky2_xmit_frame() after TX timeout During TX timeout procedure dev could be awoken too early, e.g. by sky2_complete_tx() called from sky2_down(). Then sky2_xmit_frame() can run while buffers are freed causing an oops. This patch fixes it by adding netif_device_present() test in sky2_tx_complete(). Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=14925 With debugging by: Mike McCormack Reported-by: Berck E. Nash Tested-by: Berck E. Nash Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- drivers/net/sky2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1c01b96c961..7650f739a81 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1844,7 +1844,8 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) sky2->tx_cons = idx; smp_mb(); - if (tx_avail(sky2) > MAX_SKB_TX_LE + 4) + /* Wake unless it's detached, and called e.g. from sky2_down() */ + if (tx_avail(sky2) > MAX_SKB_TX_LE + 4 && netif_device_present(dev)) netif_wake_queue(dev); } -- cgit v1.2.3 From 15e184afa83a45cf8bafdb9dc906b97a8fbc974f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 11 Jan 2010 00:05:43 -0800 Subject: Input: add compat support for sysfs and /proc capabilities output Input core displays capabilities bitmasks in form of one or more longs printed in hex form and separated by spaces. Unfortunately it does not work well for 32-bit applications running on 64-bit kernels since applications expect that number is "worth" only 32 bits when kernel advances by 64 bits. Fix that by ensuring that output produced for compat tasks uses 32-bit units. Reported-and-tested-by: Michael Tokarev Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 86 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/input/input.c b/drivers/input/input.c index ab060710688..30b503b8d67 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -24,6 +24,7 @@ #include #include #include +#include "input-compat.h" MODULE_AUTHOR("Vojtech Pavlik "); MODULE_DESCRIPTION("Input core"); @@ -764,6 +765,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han return error; } +#ifdef CONFIG_COMPAT + +static int input_bits_to_string(char *buf, int buf_size, + unsigned long bits, bool skip_empty) +{ + int len = 0; + + if (INPUT_COMPAT_TEST) { + u32 dword = bits >> 32; + if (dword || !skip_empty) + len += snprintf(buf, buf_size, "%x ", dword); + + dword = bits & 0xffffffffUL; + if (dword || !skip_empty || len) + len += snprintf(buf + len, max(buf_size - len, 0), + "%x", dword); + } else { + if (bits || !skip_empty) + len += snprintf(buf, buf_size, "%lx", bits); + } + + return len; +} + +#else /* !CONFIG_COMPAT */ + +static int input_bits_to_string(char *buf, int buf_size, + unsigned long bits, bool skip_empty) +{ + return bits || !skip_empty ? + snprintf(buf, buf_size, "%lx", bits) : 0; +} + +#endif #ifdef CONFIG_PROC_FS @@ -832,14 +867,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, unsigned long *bitmap, int max) { int i; - - for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) - if (bitmap[i]) - break; + bool skip_empty = true; + char buf[18]; seq_printf(seq, "B: %s=", name); - for (; i >= 0; i--) - seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : ""); + + for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) { + if (input_bits_to_string(buf, sizeof(buf), + bitmap[i], skip_empty)) { + skip_empty = false; + seq_printf(seq, "%s%s", buf, i > 0 ? " " : ""); + } + } + + /* + * If no output was produced print a single 0. + */ + if (skip_empty) + seq_puts(seq, "0"); + seq_putc(seq, '\n'); } @@ -1128,14 +1174,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, { int i; int len = 0; + bool skip_empty = true; + + for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) { + len += input_bits_to_string(buf + len, max(buf_size - len, 0), + bitmap[i], skip_empty); + if (len) { + skip_empty = false; + if (i > 0) + len += snprintf(buf + len, max(buf_size - len, 0), " "); + } + } - for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) - if (bitmap[i]) - break; - - for (; i >= 0; i--) - len += snprintf(buf + len, max(buf_size - len, 0), - "%lx%s", bitmap[i], i > 0 ? " " : ""); + /* + * If no output was produced print a single 0. + */ + if (len == 0) + len = snprintf(buf, buf_size, "%d", 0); if (add_cr) len += snprintf(buf + len, max(buf_size - len, 0), "\n"); @@ -1150,7 +1205,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev, \ { \ struct input_dev *input_dev = to_input_dev(dev); \ int len = input_print_bitmap(buf, PAGE_SIZE, \ - input_dev->bm##bit, ev##_MAX, 1); \ + input_dev->bm##bit, ev##_MAX, \ + true); \ return min_t(int, len, PAGE_SIZE); \ } \ static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL) @@ -1214,7 +1270,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, len = input_print_bitmap(&env->buf[env->buflen - 1], sizeof(env->buf) - env->buflen, - bitmap, max, 0); + bitmap, max, false); if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; -- cgit v1.2.3 From a2342f46437cde56803a36fdf94da635a74ad41c Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Sat, 9 Jan 2010 23:32:06 +0100 Subject: sata_promise: don't classify overruns as HSM errors When sata_promise encounters an overrun or underrun error it translates that to a libata AC_ERR_HSM, causing a hard reset. Since over/under-runs were thought to be rare and transient, this action seemed reasonable. Unfortunately it turns out that the controller throws overrun errors when e.g. hal polls a CD or DVD writer containing blank media, causing long sequences of hard resets and retries before EH finally gives up. This patch updates sata_promise to classify over/under-runs as AC_ERR_OTHER instead. This allows libata EH and upper layers to retry or fail the operation as they see fit without the disruption caused by repeated hard resets. This fixes a problem using a DVD-RAM drive with sata_promise, reported by Thomas Schorpp. I also tested it on a DVD-RW drive. Signed-off-by: Mikael Pettersson Tested-by: thomas schorpp Signed-off-by: Jeff Garzik --- drivers/ata/sata_promise.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 07d8d00b4d3..63306285c84 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -862,7 +862,7 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, if (port_status & PDC_DRIVE_ERR) ac_err_mask |= AC_ERR_DEV; if (port_status & (PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR)) - ac_err_mask |= AC_ERR_HSM; + ac_err_mask |= AC_ERR_OTHER; if (port_status & (PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR)) ac_err_mask |= AC_ERR_ATA_BUS; if (port_status & (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC2_HTO_ERR -- cgit v1.2.3 From 0b67c7439fe2a5d76602de36854c88e2beab00b0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 11 Jan 2010 17:03:11 +0900 Subject: ata_piix: enable 32bit PIO on SATA piix Commit 871af1210f13966ab911ed2166e4ab2ce775b99d enabled 32bit PIO for PATA piix but didn't for SATA. There's no reason not to use 32bit PIO on SATA piix. Enable it. Signed-off-by: Tejun Heo Cc: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 19136a7e106..6f3f2257d0f 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -329,7 +329,7 @@ static struct ata_port_operations ich_pata_ops = { }; static struct ata_port_operations piix_sata_ops = { - .inherits = &ata_bmdma_port_ops, + .inherits = &ata_bmdma32_port_ops, }; static struct ata_port_operations piix_sidpr_sata_ops = { -- cgit v1.2.3 From 5040ab67a2c6d5710ba497dc52a8f7035729d7b0 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 11 Jan 2010 11:14:44 +0900 Subject: libata: retry link resume if necessary Interestingly, when SIDPR is used in ata_piix, writes to DET in SControl sometimes get ignored leading to detection failure. Update sata_link_resume() such that it reads back SControl after clearing DET and retry if it's not clear. Signed-off-by: Tejun Heo Reported-by: fengxiangjun Reported-by: Jim Faulkner Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 22ff51bdbc8..6728328f3be 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3790,21 +3790,45 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params, int sata_link_resume(struct ata_link *link, const unsigned long *params, unsigned long deadline) { + int tries = ATA_LINK_RESUME_TRIES; u32 scontrol, serror; int rc; if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) return rc; - scontrol = (scontrol & 0x0f0) | 0x300; + /* + * Writes to SControl sometimes get ignored under certain + * controllers (ata_piix SIDPR). Make sure DET actually is + * cleared. + */ + do { + scontrol = (scontrol & 0x0f0) | 0x300; + if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) + return rc; + /* + * Some PHYs react badly if SStatus is pounded + * immediately after resuming. Delay 200ms before + * debouncing. + */ + msleep(200); - if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) - return rc; + /* is SControl restored correctly? */ + if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) + return rc; + } while ((scontrol & 0xf0f) != 0x300 && --tries); - /* Some PHYs react badly if SStatus is pounded immediately - * after resuming. Delay 200ms before debouncing. - */ - msleep(200); + if ((scontrol & 0xf0f) != 0x300) { + ata_link_printk(link, KERN_ERR, + "failed to resume link (SControl %X)\n", + scontrol); + return 0; + } + + if (tries < ATA_LINK_RESUME_TRIES) + ata_link_printk(link, KERN_WARNING, + "link resume succeeded after %d retries\n", + ATA_LINK_RESUME_TRIES - tries); if ((rc = sata_link_debounce(link, params, deadline))) return rc; -- cgit v1.2.3 From d8e292093a3a78a7967757e90abbe64869e4cb7c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Jan 2010 00:45:33 +0100 Subject: drm/i915: Fix resume regression on MSI Wind U100 w/o KMS Commit cbda12d77ea590082edb6d30bd342a67ebc459e0 (drm/i915: implement new pm ops for i915), among other things, removed the .suspend and .resume pointers from the struct drm_driver object in i915_drv.c, which broke resume without KMS on my MSI Wind U100. Fix this by reverting that part of commit cbda12d77ea59. Signed-off-by: Rafael J. Wysocki Acked-by: Jesse Barnes [anholt: added comment explaining when .suspend/.resume matter] Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2ffffd7ae09..66f7bac2ee5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -464,6 +464,11 @@ static struct drm_driver driver = { .lastclose = i915_driver_lastclose, .preclose = i915_driver_preclose, .postclose = i915_driver_postclose, + + /* Used in place of i915_pm_ops for non-DRIVER_MODESET */ + .suspend = i915_suspend, + .resume = i915_resume, + .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, -- cgit v1.2.3 From 6207937d4feea000913e8ca23fe20c7744be7847 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 6 Jan 2010 09:49:31 +0800 Subject: drm/i915: Don't use the child device parsed from VBT to setup HDMI/DP On some boxes the BIOS will report different child device arrays when the system is booted with/without the dock. In such case the HDMI/DP port can't be setup correctly. So revert two commits (fc816655236cd9da162356e96e74c7cfb0834d92/ 6e36595a2131e7ed5ee2674be54b2713ba7f0490) that use the child device parsed from VBT to setup HDMI/DP. http://bugzilla.kernel.org/show_bug.cgi?id=14854 http://bugzilla.kernel.org/show_bug.cgi?id=14860 Signed-off-by: Zhao Yakui Tested-by: Sean Young Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 52 +-------------------------------------- drivers/gpu/drm/i915/intel_hdmi.c | 50 ------------------------------------- 2 files changed, 1 insertion(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1349d9fd01c..0ec07e43d6c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1289,53 +1289,7 @@ intel_dp_hot_plug(struct intel_output *intel_output) if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) intel_dp_check_link_status(intel_output); } -/* - * Enumerate the child dev array parsed from VBT to check whether - * the given DP is present. - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it is assumed that the given - * DP is present. - */ -static int dp_is_present_in_vbt(struct drm_device *dev, int dp_reg) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct child_device_config *p_child; - int i, dp_port, ret; - - if (!dev_priv->child_dev_num) - return 1; - - dp_port = 0; - if (dp_reg == DP_B || dp_reg == PCH_DP_B) - dp_port = PORT_IDPB; - else if (dp_reg == DP_C || dp_reg == PCH_DP_C) - dp_port = PORT_IDPC; - else if (dp_reg == DP_D || dp_reg == PCH_DP_D) - dp_port = PORT_IDPD; - - ret = 0; - for (i = 0; i < dev_priv->child_dev_num; i++) { - p_child = dev_priv->child_dev + i; - /* - * If the device type is not DP, continue. - */ - if (p_child->device_type != DEVICE_TYPE_DP && - p_child->device_type != DEVICE_TYPE_eDP) - continue; - /* Find the eDP port */ - if (dp_reg == DP_A && p_child->device_type == DEVICE_TYPE_eDP) { - ret = 1; - break; - } - /* Find the DP port */ - if (p_child->dvo_port == dp_port) { - ret = 1; - break; - } - } - return ret; -} + void intel_dp_init(struct drm_device *dev, int output_reg) { @@ -1345,10 +1299,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) struct intel_dp_priv *dp_priv; const char *name = NULL; - if (!dp_is_present_in_vbt(dev, output_reg)) { - DRM_DEBUG_KMS("DP is not present. Ignore it\n"); - return; - } intel_output = kcalloc(sizeof(struct intel_output) + sizeof(struct intel_dp_priv), 1, GFP_KERNEL); if (!intel_output) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 06431941b23..0e268deed76 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -225,52 +225,6 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { .destroy = intel_hdmi_enc_destroy, }; -/* - * Enumerate the child dev array parsed from VBT to check whether - * the given HDMI is present. - * If it is present, return 1. - * If it is not present, return false. - * If no child dev is parsed from VBT, it assumes that the given - * HDMI is present. - */ -static int hdmi_is_present_in_vbt(struct drm_device *dev, int hdmi_reg) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct child_device_config *p_child; - int i, hdmi_port, ret; - - if (!dev_priv->child_dev_num) - return 1; - - if (hdmi_reg == SDVOB) - hdmi_port = DVO_B; - else if (hdmi_reg == SDVOC) - hdmi_port = DVO_C; - else if (hdmi_reg == HDMIB) - hdmi_port = DVO_B; - else if (hdmi_reg == HDMIC) - hdmi_port = DVO_C; - else if (hdmi_reg == HDMID) - hdmi_port = DVO_D; - else - return 0; - - ret = 0; - for (i = 0; i < dev_priv->child_dev_num; i++) { - p_child = dev_priv->child_dev + i; - /* - * If the device type is not HDMI, continue. - */ - if (p_child->device_type != DEVICE_TYPE_HDMI) - continue; - /* Find the HDMI port */ - if (p_child->dvo_port == hdmi_port) { - ret = 1; - break; - } - } - return ret; -} void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -278,10 +232,6 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) struct intel_output *intel_output; struct intel_hdmi_priv *hdmi_priv; - if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) { - DRM_DEBUG_KMS("HDMI is not present. Ignored it \n"); - return; - } intel_output = kcalloc(sizeof(struct intel_output) + sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); if (!intel_output) -- cgit v1.2.3 From 6a304caf0bf9c429fc261f260b86cabf5bde2cbb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:19 +0800 Subject: drm/i915: Read the response after issuing DDC bus switch command For some SDVO cards based on conexant chip, we can't read the EDID if we don't read the response after issuing SDVO DDC bus switch command. From the SDVO spec once when another I2C transaction is finished after completing the I2C transaction of issuing the bus switch command, it will be switched back to the SDVO internal state again. So we can't initiate a new I2C transaction to read the response after issuing the DDC bus switch command. Instead we should issue DDC bus switch command and read the response in the same I2C transaction. https://bugs.freedesktop.org/show_bug.cgi?id=23842 https://bugs.freedesktop.org/show_bug.cgi?id=24458 https://bugs.freedesktop.org/show_bug.cgi?id=24522 https://bugs.freedesktop.org/show_bug.cgi?id=24282 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_sdvo.c | 57 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index de5144c8c15..f899afd924b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -462,14 +462,63 @@ static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) } /** - * Don't check status code from this as it switches the bus back to the - * SDVO chips which defeats the purpose of doing a bus switch in the first - * place. + * Try to read the response after issuie the DDC switch command. But it + * is noted that we must do the action of reading response and issuing DDC + * switch command in one I2C transaction. Otherwise when we try to start + * another I2C transaction after issuing the DDC bus switch, it will be + * switched to the internal SDVO register. */ static void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, u8 target) { - intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 out_buf[2], cmd_buf[2], ret_value[2], ret; + struct i2c_msg msgs[] = { + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 2, + .buf = out_buf, + }, + /* the following two are to read the response */ + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = 0, + .len = 1, + .buf = cmd_buf, + }, + { + .addr = sdvo_priv->slave_addr >> 1, + .flags = I2C_M_RD, + .len = 1, + .buf = ret_value, + }, + }; + + intel_sdvo_debug_write(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, + &target, 1); + /* write the DDC switch command argument */ + intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0, target); + + out_buf[0] = SDVO_I2C_OPCODE; + out_buf[1] = SDVO_CMD_SET_CONTROL_BUS_SWITCH; + cmd_buf[0] = SDVO_I2C_CMD_STATUS; + cmd_buf[1] = 0; + ret_value[0] = 0; + ret_value[1] = 0; + + ret = i2c_transfer(intel_output->i2c_bus, msgs, 3); + if (ret != 3) { + /* failure in I2C transfer */ + DRM_DEBUG_KMS("I2c transfer returned %d\n", ret); + return; + } + if (ret_value[0] != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG_KMS("DDC switch command returns response %d\n", + ret_value[0]); + return; + } + return; } static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1) -- cgit v1.2.3 From 7c3f0a2726fed78e0e0afe3b6fc3c1f5b298e447 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 10:58:20 +0800 Subject: drm/i915: try another possible DDC bus for the SDVO device with multiple outputs There exist multiple DDC buses for the SDVO cards with multiple outputs. When we can't get the EDID by using the select DDC bus, we can try the other possible DDC bus to see whether the EDID can be obtained. https://bugs.freedesktop.org/show_bug.cgi?id=23842 Signed-off-by: Zhao Yakui Tested-by: Sebastien Caty Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_sdvo.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f899afd924b..eaacfd0920d 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1628,6 +1628,32 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response) edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); + /* This is only applied to SDVO cards with multiple outputs */ + if (edid == NULL && intel_sdvo_multifunc_encoder(intel_output)) { + uint8_t saved_ddc, temp_ddc; + saved_ddc = sdvo_priv->ddc_bus; + temp_ddc = sdvo_priv->ddc_bus >> 1; + /* + * Don't use the 1 as the argument of DDC bus switch to get + * the EDID. It is used for SDVO SPD ROM. + */ + while(temp_ddc > 1) { + sdvo_priv->ddc_bus = temp_ddc; + edid = drm_get_edid(&intel_output->base, + intel_output->ddc_bus); + if (edid) { + /* + * When we can get the EDID, maybe it is the + * correct DDC bus. Update it. + */ + sdvo_priv->ddc_bus = temp_ddc; + break; + } + temp_ddc >>= 1; + } + if (edid == NULL) + sdvo_priv->ddc_bus = saved_ddc; + } /* when there is no edid and no monitor is connected with VGA * port, try to use the CRT ddc to read the EDID for DVI-connector */ -- cgit v1.2.3 From b9241ea31fae4887104e5d1b3b18f4009c25a0c4 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 25 Nov 2009 13:09:39 +0800 Subject: drm/i915: Don't wait interruptible for possible plane buffer flush When we setup buffer for display plane, we'll check any pending required GPU flush and possible make interruptible wait for flush complete. But that wait would be most possibly to fail in case of signals received for X process, which will then fail modeset process and put display engine in unconsistent state. The result could be blank screen or CPU hang, and DDX driver would always turn on outputs DPMS after whatever modeset fails or not. So this one creates new helper for setup display plane buffer, and when needing flush using uninterruptible wait for that. This one should fix bug like https://bugs.freedesktop.org/show_bug.cgi?id=24009. Also fixing mode switch stress test on Ironlake. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 51 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 2 +- 3 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 29dd6762696..445c49c6c39 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -864,6 +864,7 @@ int i915_do_wait_request(struct drm_device *dev, uint32_t seqno, int interruptib int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); +int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj); int i915_gem_attach_phys_object(struct drm_device *dev, struct drm_gem_object *obj, int id); void i915_gem_detach_phys_object(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2748609f05b..0f4afa3b03f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2837,6 +2837,57 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) return 0; } +/* + * Prepare buffer for display plane. Use uninterruptible for possible flush + * wait, as in modesetting process we're not supposed to be interrupted. + */ +int +i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + uint32_t old_write_domain, old_read_domains; + int ret; + + /* Not valid to be called on unbound objects. */ + if (obj_priv->gtt_space == NULL) + return -EINVAL; + + i915_gem_object_flush_gpu_write_domain(obj); + + /* Wait on any GPU rendering and flushing to occur. */ + if (obj_priv->active) { +#if WATCH_BUF + DRM_INFO("%s: object %p wait for seqno %08x\n", + __func__, obj, obj_priv->last_rendering_seqno); +#endif + ret = i915_do_wait_request(dev, obj_priv->last_rendering_seqno, 0); + if (ret != 0) + return ret; + } + + old_write_domain = obj->write_domain; + old_read_domains = obj->read_domains; + + obj->read_domains &= I915_GEM_DOMAIN_GTT; + + i915_gem_object_flush_cpu_write_domain(obj); + + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; + obj->write_domain = I915_GEM_DOMAIN_GTT; + obj_priv->dirty = 1; + + trace_i915_gem_object_change_domain(obj, + old_read_domains, + old_write_domain); + + return 0; +} + /** * Moves a single object to the CPU read, and possibly write domain. * diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 42e8c031c2c..4b96a54b8e4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1207,7 +1207,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, return ret; } - ret = i915_gem_object_set_to_gtt_domain(obj, 1); + ret = i915_gem_object_set_to_display_plane(obj); if (ret != 0) { i915_gem_object_unpin(obj); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From 3890ddf56dbc0f804953198e65a7e406ed654576 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 12 Jan 2010 11:16:57 -0500 Subject: drm/radeon/kms: fix up LVDS handling on macs (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on radeonfb code and recent ddx fix. v2: minor formatting fix from Michel Dänzer Signed-off-by: Alex Deucher Reviewed-by: Michel Dänzer Tested-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 981508ff703..38e45e231ef 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -46,6 +46,7 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; int panel_pwr_delay = 2000; + bool is_mac = false; DRM_DEBUG("\n"); if (radeon_encoder->enc_priv) { @@ -58,6 +59,15 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) } } + /* macs (and possibly some x86 oem systems?) wire up LVDS strangely + * Taken from radeonfb. + */ + if ((rdev->mode_info.connector_table == CT_IBOOK) || + (rdev->mode_info.connector_table == CT_POWERBOOK_EXTERNAL) || + (rdev->mode_info.connector_table == CT_POWERBOOK_INTERNAL) || + (rdev->mode_info.connector_table == CT_POWERBOOK_VGA)) + is_mac = true; + switch (mode) { case DRM_MODE_DPMS_ON: disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN); @@ -74,6 +84,8 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON); + if (is_mac) + lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); udelay(panel_pwr_delay * 1000); WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); @@ -85,7 +97,14 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; - lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + if (is_mac) { + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_EN); + } else { + WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); + } udelay(panel_pwr_delay * 1000); WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); -- cgit v1.2.3 From b042589ca038e647fa1e2bb4e7ac3963688479b8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Jan 2010 19:47:38 -0500 Subject: drm/radeon/kms/r6xx+: make irq handler less verbose Unhandled vectors can be safely ignored, no need to spam the kernel log by default. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1f4f83d6fbe..9757962146f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2729,7 +2729,7 @@ restart_ih: } break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; @@ -2749,7 +2749,7 @@ restart_ih: } break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; @@ -2798,7 +2798,7 @@ restart_ih: } break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } break; @@ -2812,7 +2812,7 @@ restart_ih: DRM_DEBUG("IH: CP EOP\n"); break; default: - DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); + DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); break; } -- cgit v1.2.3 From 1b24203e51072b6e76aff8c74bdd67eb3b34a724 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 11 Jan 2010 15:02:31 -0500 Subject: drm/radeon/kms/rv100: reject modes > 135 Mhz on DVI (v2) Due to heat issues. Fixes fdo bug 25992 v2: fix typo noticed by Maarten Maathuis Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9da10dd5df8..55266416fa4 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -900,10 +900,18 @@ static void radeon_dvi_force(struct drm_connector *connector) static int radeon_dvi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct drm_device *dev = connector->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_connector *radeon_connector = to_radeon_connector(connector); /* XXX check mode bandwidth */ + /* clocks over 135 MHz have heat issues with DVI on RV100 */ + if (radeon_connector->use_digital && + (rdev->family == CHIP_RV100) && + (mode->clock > 135000)) + return MODE_CLOCK_HIGH; + if (radeon_connector->use_digital && (mode->clock > 165000)) { if ((radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I) || (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) || -- cgit v1.2.3 From 11f3b59e3654c66c4e8ef2c48f8138b78bf440da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Mon, 11 Jan 2010 08:58:38 +0100 Subject: drm/radeon/kms: Fix crash getting TV info with no BIOS. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michel Dänzer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_combios.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 7914455c96c..579c8920e08 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -687,6 +687,9 @@ radeon_combios_get_tv_info(struct radeon_device *rdev) uint16_t tv_info; enum radeon_tv_std tv_std = TV_STD_NTSC; + if (rdev->bios == NULL) + return tv_std; + tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); if (tv_info) { if (RBIOS8(tv_info + 6) == 'T') { -- cgit v1.2.3 From 9270eb1b496cb002d75f49ef82c9ef4cbd22a5a0 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 13 Jan 2010 09:21:49 +1000 Subject: drm/radeon/kms: only evict to GTT if CP is ready Testing GTT ready might be more correct but cp.ready works fine and has been tested on irc by 2-3 ppl. fixes bug k.org 15035 and fd.o 25733 Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_ttm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index a00450743d6..db820ae9a03 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -215,7 +215,10 @@ static void radeon_evict_flags(struct ttm_buffer_object *bo, rbo = container_of(bo, struct radeon_bo, tbo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: - radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); + if (rbo->rdev->cp.ready == false) + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_CPU); + else + radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_GTT); break; case TTM_PL_TT: default: -- cgit v1.2.3 From 2c761270d5520dd84ab0b4e47c24d99ff8503c38 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Tue, 12 Jan 2010 17:39:16 +1100 Subject: lib: Introduce generic list_sort function There are two copies of list_sort() in the tree already, one in the DRM code, another in ubifs. Now XFS needs this as well. Create a generic list_sort() function from the ubifs version and convert existing users to it so we don't end up with yet another copy in the tree. Signed-off-by: Dave Chinner Acked-by: Dave Airlie Acked-by: Artem Bityutskiy Signed-off-by: Linus Torvalds --- drivers/gpu/drm/drm_modes.c | 90 ++------------------------------------------- 1 file changed, 4 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 6d81a02463a..76d63394c77 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1,9 +1,4 @@ /* - * The list_sort function is (presumably) licensed under the GPL (see the - * top level "COPYING" file for details). - * - * The remainder of this file is: - * * Copyright © 1997-2003 by The XFree86 Project, Inc. * Copyright © 2007 Dave Airlie * Copyright © 2007-2008 Intel Corporation @@ -36,6 +31,7 @@ */ #include +#include #include "drmP.h" #include "drm.h" #include "drm_crtc.h" @@ -855,6 +851,7 @@ EXPORT_SYMBOL(drm_mode_prune_invalid); /** * drm_mode_compare - compare modes for favorability + * @priv: unused * @lh_a: list_head for first mode * @lh_b: list_head for second mode * @@ -868,7 +865,7 @@ EXPORT_SYMBOL(drm_mode_prune_invalid); * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or * positive if @lh_b is better than @lh_a. */ -static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b) +static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b) { struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head); struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head); @@ -885,85 +882,6 @@ static int drm_mode_compare(struct list_head *lh_a, struct list_head *lh_b) return diff; } -/* FIXME: what we don't have a list sort function? */ -/* list sort from Mark J Roberts (mjr@znex.org) */ -void list_sort(struct list_head *head, - int (*cmp)(struct list_head *a, struct list_head *b)) -{ - struct list_head *p, *q, *e, *list, *tail, *oldhead; - int insize, nmerges, psize, qsize, i; - - list = head->next; - list_del(head); - insize = 1; - for (;;) { - p = oldhead = list; - list = tail = NULL; - nmerges = 0; - - while (p) { - nmerges++; - q = p; - psize = 0; - for (i = 0; i < insize; i++) { - psize++; - q = q->next == oldhead ? NULL : q->next; - if (!q) - break; - } - - qsize = insize; - while (psize > 0 || (qsize > 0 && q)) { - if (!psize) { - e = q; - q = q->next; - qsize--; - if (q == oldhead) - q = NULL; - } else if (!qsize || !q) { - e = p; - p = p->next; - psize--; - if (p == oldhead) - p = NULL; - } else if (cmp(p, q) <= 0) { - e = p; - p = p->next; - psize--; - if (p == oldhead) - p = NULL; - } else { - e = q; - q = q->next; - qsize--; - if (q == oldhead) - q = NULL; - } - if (tail) - tail->next = e; - else - list = e; - e->prev = tail; - tail = e; - } - p = q; - } - - tail->next = list; - list->prev = tail; - - if (nmerges <= 1) - break; - - insize *= 2; - } - - head->next = list; - head->prev = list->prev; - list->prev->next = head; - list->prev = head; -} - /** * drm_mode_sort - sort mode list * @mode_list: list to sort @@ -975,7 +893,7 @@ void list_sort(struct list_head *head, */ void drm_mode_sort(struct list_head *mode_list) { - list_sort(mode_list, drm_mode_compare); + list_sort(NULL, mode_list, drm_mode_compare); } EXPORT_SYMBOL(drm_mode_sort); -- cgit v1.2.3 From bb7d3f24c71e528989501617651b669fbed798cb Mon Sep 17 00:00:00 2001 From: "Bryn M. Reeves" Date: Thu, 12 Nov 2009 18:31:54 +0000 Subject: [SCSI] megaraid_sas: remove sysfs poll_mode_io world writeable permissions /sys/bus/pci/drivers/megaraid_sas/poll_mode_io defaults to being world-writable, which seems bad (letting any user affect kernel driver behavior). This turns off group and user write permissions, so that on typical production systems only root can write to it. Signed-off-by: Bryn M. Reeves Signed-off-by: Linus Torvalds --- drivers/scsi/megaraid/megaraid_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 99ff99e45be..708ea3157b6 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -4046,7 +4046,7 @@ megasas_aen_polling(struct work_struct *work) } -static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, +static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR, megasas_sysfs_show_poll_mode_io, megasas_sysfs_set_poll_mode_io); -- cgit v1.2.3 From 70a94d6a35072b62f808155f117f00485a395f03 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 13 Jan 2010 16:15:11 +1000 Subject: drm: fix crtc no modes printf + typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Toralf Förster pointed out the typo, the fact I forget the if statement is purely personal fail. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 077313f0d47..1c47ea25337 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -1032,7 +1032,8 @@ bool drm_helper_initial_config(struct drm_device *dev) /* * we shouldn't end up with no modes here. */ - printk(KERN_INFO "No connectors reported conncted with modes\n"); + if (count == 0) + printk(KERN_INFO "No connectors reported connected with modes\n"); drm_setup_crtcs(dev); -- cgit v1.2.3 From ef14587706521287f1c7ea3326e732f7d86dd096 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Wed, 13 Jan 2010 13:38:59 +0800 Subject: drm: change drm set mode messages as DRM_DEBUG Following drm info repeat 207 times during one hour, it's quite annoying [ 1266.286747] [drm] TV-19: set mode NTSC 480i 0 Change from DRM_INFO to DRM_DEBUG Signed-off-by: Dave Young Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_crtc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 1c47ea25337..7d0f00a935f 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -702,7 +702,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder->crtc != crtc) continue; - DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), + DRM_DEBUG("%s: set mode %s %x\n", drm_get_encoder_name(encoder), mode->name, mode->base.id); encoder_funcs = encoder->helper_private; encoder_funcs->mode_set(encoder, mode, adjusted_mode); -- cgit v1.2.3 From 4a18b3ab6ed537b055e3fcfca64ab870b4f9acf0 Mon Sep 17 00:00:00 2001 From: Tai-hwa Liang Date: Wed, 13 Jan 2010 00:16:27 -0800 Subject: Input: pmouse - move Sentelic probe down the list Sentelic probes confuse IBM trackpoints so they stop responding to TP_READ_ID command. See: http://bugzilla.kernel.org/show_bug.cgi?id=14970 Let's move FSP detection lower so it is probed after trackpoint and others, just before we strat probing for Intellimouse Explorer. Signed-off-by: Tai-hwa Liang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/psmouse-base.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cabf4e1caac..9774bdfaa48 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -690,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse, max_proto = PSMOUSE_IMEX; } -/* - * Try Finger Sensing Pad - */ - if (max_proto > PSMOUSE_IMEX) { - if (fsp_detect(psmouse, set_properties) == 0) { - if (!set_properties || fsp_init(psmouse) == 0) - return PSMOUSE_FSP; -/* - * Init failed, try basic relative protocols - */ - max_proto = PSMOUSE_IMEX; - } - } if (max_proto > PSMOUSE_IMEX) { if (genius_detect(psmouse, set_properties) == 0) @@ -718,6 +705,21 @@ static int psmouse_extensions(struct psmouse *psmouse, return PSMOUSE_TOUCHKIT_PS2; } +/* + * Try Finger Sensing Pad. We do it here because its probe upsets + * Trackpoint devices (causing TP_READ_ID command to time out). + */ + if (max_proto > PSMOUSE_IMEX) { + if (fsp_detect(psmouse, set_properties) == 0) { + if (!set_properties || fsp_init(psmouse) == 0) + return PSMOUSE_FSP; +/* + * Init failed, try basic relative protocols + */ + max_proto = PSMOUSE_IMEX; + } + } + /* * Reset to defaults in case the device got confused by extended * protocol probes. Note that we follow up with full reset because -- cgit v1.2.3 From c332e9fcc5289698350d39d4d22c3ed5257d7a80 Mon Sep 17 00:00:00 2001 From: Tai-hwa Liang Date: Wed, 13 Jan 2010 00:25:35 -0800 Subject: Input: sentelic - fix left/right horizontal scroll mapping Signed-off-by: Tai-hwa Liang Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/sentelic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 77b9fd0b3fb..81a6b81cb2f 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -2,7 +2,7 @@ * Finger Sensing Pad PS/2 mouse driver. * * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. - * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. + * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -658,9 +658,9 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) if (packet[3] & BIT(1)) button_status |= 0x0f; /* wheel up */ if (packet[3] & BIT(2)) - button_status |= BIT(5);/* horizontal left */ + button_status |= BIT(4);/* horizontal left */ if (packet[3] & BIT(3)) - button_status |= BIT(4);/* horizontal right */ + button_status |= BIT(5);/* horizontal right */ /* push back to packet queue */ if (button_status != 0) packet[3] = button_status; -- cgit v1.2.3 From c5cae661d6cf808b6984762f763261adf35f3eb7 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 17 Dec 2009 13:57:09 +0000 Subject: xen: fix hang on suspend. In 65f63384 "xen: improve error handling in do_suspend" I said: - xs_suspend()/xs_resume() and dpm_suspend_noirq()/dpm_resume_noirq() were not nested in the obvious way. and changed the ordering of the calls as so: BEFORE AFTER xs_suspend dpm_suspend_noirq dpm_suspend_noirq xs_suspend *SUSPEND* *SUSPEND* dpm_resume_noirq dpm_resume_noirq xs_resume xs_resume Clearly this is not an improvement and I was talking rubbish. In particular the new ordering is susceptible to a hang if a xenstore write is in progress at the point at which the suspend kicks in. When the suspend process calls xs_suspend it tries to take the request_mutex but if a write is in progress it could be looping in xenbus_xs.c:read_reply() waiting for something to arrive on &xs_state.reply_list while holding the request_mutex (taken in the caller of read_reply). However if we have done dpm_suspend_noirq before xs_suspend then we won't get any more xenstore interrupts and process_msg() will never be woken up to add anything to the reply_list. Fix this by calling xs_suspend before dpm_suspend_noirq. If dpm_suspend_noirq fails then make sure we go through the xs_suspend_cancel() code path. Signed-off-by: Ian Campbell Acked-by: Jeremy Fitzhardinge Cc: Stable Kernel --- drivers/xen/manage.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index c4997930afc..5d42d55e299 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -102,15 +102,15 @@ static void do_suspend(void) goto out_thaw; } + printk(KERN_DEBUG "suspending xenstore...\n"); + xs_suspend(); + err = dpm_suspend_noirq(PMSG_SUSPEND); if (err) { printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err); goto out_resume; } - printk(KERN_DEBUG "suspending xenstore...\n"); - xs_suspend(); - err = stop_machine(xen_suspend, &cancelled, cpumask_of(0)); dpm_resume_noirq(PMSG_RESUME); @@ -120,13 +120,13 @@ static void do_suspend(void) cancelled = 1; } +out_resume: if (!cancelled) { xen_arch_resume(); xs_resume(); } else xs_suspend_cancel(); -out_resume: dpm_resume_end(PMSG_RESUME); /* Make sure timer events get retriggered on all CPUs */ -- cgit v1.2.3 From 42590a75019a50012f25a962246498dead428433 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 4 Jan 2010 16:16:23 +0900 Subject: x86/agp: Fix agp_amd64_init and agp_amd64_cleanup This fixes the regression introduced by the commit f405d2c02395a74d3883bd03ded36457aa3697ad. The above commit fixes the following issue: http://marc.info/?l=linux-kernel&m=126192729110083&w=2 However, it doesn't work properly when you remove and insert the agp_amd64 module again. agp_amd64_init() and agp_amd64_cleanup should be called only when gart_iommu is not called earlier (that is, the GART IOMMU is not enabled). We need to use 'gart_iommu_aperture' to see if GART IOMMU is enabled or not. Signed-off-by: FUJITA Tomonori Cc: mitov@issp.bas.bg Cc: davej@redhat.com LKML-Reference: <20100104161603L.fujita.tomonori@lab.ntt.co.jp> Signed-off-by: Ingo Molnar --- drivers/char/agp/amd64-agp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 5aa7a586a7f..1afb8968a34 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -725,12 +725,11 @@ static struct pci_driver agp_amd64_pci_driver = { int __init agp_amd64_init(void) { int err = 0; - static int done = 0; if (agp_off) return -EINVAL; - if (done++) + if (gart_iommu_aperture) return agp_bridges_found ? 0 : -ENODEV; err = pci_register_driver(&agp_amd64_pci_driver); @@ -771,6 +770,8 @@ int __init agp_amd64_init(void) static void __exit agp_amd64_cleanup(void) { + if (gart_iommu_aperture) + return; if (aperture_resource) release_resource(aperture_resource); pci_unregister_driver(&agp_amd64_pci_driver); -- cgit v1.2.3 From d01799b2f399603ae4cecc06f6ea146c57519cb1 Mon Sep 17 00:00:00 2001 From: Przemo Firszt Date: Mon, 4 Jan 2010 12:32:00 +0100 Subject: HID: fix pad button definition in hid-wacom This fix is required for xorg driver to recognise 2 pad buttons Signed-off-by: Przemo Firszt Signed-off-by: Jiri Kosina --- drivers/hid/hid-wacom.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 74754217224..75ea66affb6 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -196,6 +196,9 @@ static int wacom_probe(struct hid_device *hdev, /* Pad */ input->evbit[0] |= BIT(EV_MSC); input->mscbit[0] |= BIT(MSC_SERIAL); + set_bit(BTN_0, input->keybit); + set_bit(BTN_1, input->keybit); + set_bit(BTN_TOOL_FINGER, input->keybit); /* Distance, rubber and mouse */ input->absbit[0] |= BIT(ABS_DISTANCE); -- cgit v1.2.3 From 23aeb61e7e1f02fb0f3b8f9e798e75537ca1731d Mon Sep 17 00:00:00 2001 From: Christian Schuerer-Waldheim Date: Wed, 6 Jan 2010 14:49:57 +0100 Subject: HID: add device IDs for new model of Apple Wireless Keyboard Added device IDs for the new model of the Apple Wireless Keyboard (November 2009). Signed-off-by: Christian Schuerer-Waldheim Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 7 +++++++ drivers/hid/hid-core.c | 3 +++ drivers/hid/hid-ids.h | 3 +++ 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 4b96e7a898c..5b4d66dc1a0 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -431,6 +431,13 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | + APPLE_ISO_KEYBOARD }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS), + .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 389cd5f0a68..eabe5f87c6c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1285,6 +1285,9 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, + { 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_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b9de32b6b10..010368e649e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -88,6 +88,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a +#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 -- cgit v1.2.3 From 0e253fdb3b5739fd8514f617ec582762bcfaea48 Mon Sep 17 00:00:00 2001 From: Przemo Firszt Date: Sat, 9 Jan 2010 15:20:03 +0100 Subject: HID: wacom: Add BTN_TOOL_FINGER for pad button reporting Without this patch xf86-input-wacom driver wasn't able to properly recognise pad button events. It was also causing some problems with button mapping. Signed-off-by: Przemo Firszt Signed-off-by: Jiri Kosina --- drivers/hid/hid-wacom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index 75ea66affb6..12dcda52920 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -142,6 +142,7 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, wdata->butstate = rw; input_report_key(input, BTN_0, rw & 0x02); input_report_key(input, BTN_1, rw & 0x01); + input_report_key(input, BTN_TOOL_FINGER, 0xf0); input_event(input, EV_MSC, MSC_SERIAL, 0xf0); input_sync(input); } -- cgit v1.2.3 From 880348653ec2eda81550a8aa37c2eb625922f695 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:29 +0100 Subject: [S390] dasd: add missing compat ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_ioctl.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 478bcdb90b6..fc7b30b4a25 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c @@ -17,7 +17,7 @@ #include #include #include - +#include #include #include #include @@ -358,9 +358,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp) } static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd, - unsigned long arg) + struct cmbdata __user *argp) { - struct cmbdata __user *argp = (void __user *) arg; size_t size = _IOC_SIZE(cmd); struct cmbdata data; int ret; @@ -376,7 +375,12 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { struct dasd_block *block = bdev->bd_disk->private_data; - void __user *argp = (void __user *)arg; + void __user *argp; + + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (void __user *)arg; if (!block) return -ENODEV; @@ -414,7 +418,7 @@ dasd_do_ioctl(struct block_device *bdev, fmode_t mode, case BIODASDCMFDISABLE: return disable_cmf(block->base->cdev); case BIODASDREADALLCMB: - return dasd_ioctl_readall_cmb(block, cmd, arg); + return dasd_ioctl_readall_cmb(block, cmd, argp); default: /* if the discipline has an ioctl method try it. */ if (block->base->discipline->ioctl) { -- cgit v1.2.3 From 44ee6a8564a89a77206b0b13cea91fc2f4ff997d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:30 +0100 Subject: [S390] cio: add missing compat ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/chsc_sch.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index cc5144b6f9d..c84ac944307 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -770,24 +771,30 @@ out_free: static long chsc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + void __user *argp; + CHSC_MSG(2, "chsc_ioctl called, cmd=%x\n", cmd); + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (void __user *)arg; switch (cmd) { case CHSC_START: - return chsc_ioctl_start((void __user *)arg); + return chsc_ioctl_start(argp); case CHSC_INFO_CHANNEL_PATH: - return chsc_ioctl_info_channel_path((void __user *)arg); + return chsc_ioctl_info_channel_path(argp); case CHSC_INFO_CU: - return chsc_ioctl_info_cu((void __user *)arg); + return chsc_ioctl_info_cu(argp); case CHSC_INFO_SCH_CU: - return chsc_ioctl_info_sch_cu((void __user *)arg); + return chsc_ioctl_info_sch_cu(argp); case CHSC_INFO_CI: - return chsc_ioctl_conf_info((void __user *)arg); + return chsc_ioctl_conf_info(argp); case CHSC_INFO_CCL: - return chsc_ioctl_conf_comp_list((void __user *)arg); + return chsc_ioctl_conf_comp_list(argp); case CHSC_INFO_CPD: - return chsc_ioctl_chpd((void __user *)arg); + return chsc_ioctl_chpd(argp); case CHSC_INFO_DCAL: - return chsc_ioctl_dcal((void __user *)arg); + return chsc_ioctl_dcal(argp); default: /* unknown ioctl number */ return -ENOIOCTLCMD; } -- cgit v1.2.3 From 8f3eabe3835449117058efaf5e90f28bf030e859 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:31 +0100 Subject: [S390] vmcp: add missing compat ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/vmcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index a6087cec55b..921dcda7767 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -139,21 +140,26 @@ vmcp_write(struct file *file, const char __user *buff, size_t count, static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct vmcp_session *session; + int __user *argp; int temp; session = (struct vmcp_session *)file->private_data; + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (int __user *)arg; if (mutex_lock_interruptible(&session->mutex)) return -ERESTARTSYS; switch (cmd) { case VMCP_GETCODE: temp = session->resp_code; mutex_unlock(&session->mutex); - return put_user(temp, (int __user *)arg); + return put_user(temp, argp); case VMCP_SETBUF: free_pages((unsigned long)session->response, get_order(session->bufsize)); session->response=NULL; - temp = get_user(session->bufsize, (int __user *)arg); + temp = get_user(session->bufsize, argp); if (get_order(session->bufsize) > 8) { session->bufsize = PAGE_SIZE; temp = -EINVAL; @@ -163,7 +169,7 @@ static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case VMCP_GETSIZE: temp = session->resp_size; mutex_unlock(&session->mutex); - return put_user(temp, (int __user *)arg); + return put_user(temp, argp); default: mutex_unlock(&session->mutex); return -ENOIOCTLCMD; -- cgit v1.2.3 From 16e1a577693a470367287281765b7daad0998fc1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:32 +0100 Subject: [S390] fs3270: add missing compat ptr conversion Add missing compat ptr conversion including two additional whitespace changes that aren't worth a separate patch. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/fs3270.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 247b2b93472..31c59b0d6df 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -322,6 +323,7 @@ fs3270_write(struct file *filp, const char __user *data, size_t count, loff_t *o static long fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + char __user *argp; struct fs3270 *fp; struct raw3270_iocb iocb; int rc; @@ -329,6 +331,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp = filp->private_data; if (!fp) return -ENODEV; + if (is_compat_task()) + argp = compat_ptr(arg); + else + argp = (char __user *)arg; rc = 0; mutex_lock(&fs3270_mutex); switch (cmd) { @@ -339,10 +345,10 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) fp->write_command = arg; break; case TUBGETI: - rc = put_user(fp->read_command, (char __user *) arg); + rc = put_user(fp->read_command, argp); break; case TUBGETO: - rc = put_user(fp->write_command,(char __user *) arg); + rc = put_user(fp->write_command, argp); break; case TUBGETMOD: iocb.model = fp->view.model; @@ -351,8 +357,7 @@ fs3270_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) iocb.pf_cnt = 24; iocb.re_cnt = 20; iocb.map = 0; - if (copy_to_user((char __user *) arg, &iocb, - sizeof(struct raw3270_iocb))) + if (copy_to_user(argp, &iocb, sizeof(struct raw3270_iocb))) rc = -EFAULT; break; } @@ -511,8 +516,8 @@ static const struct file_operations fs3270_fops = { .write = fs3270_write, /* write */ .unlocked_ioctl = fs3270_ioctl, /* ioctl */ .compat_ioctl = fs3270_ioctl, /* ioctl */ - .open = fs3270_open, /* open */ - .release = fs3270_close, /* release */ + .open = fs3270_open, /* open */ + .release = fs3270_close, /* release */ }; /* -- cgit v1.2.3 From 957a37ad587f3ef1022f1fe434d818cbed38eb95 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:36 +0100 Subject: [S390] tape_block: remove ioctl function This is just a complicated construct which always returns -EINVAL. Just remove it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_block.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 96816149368..8d3d720737d 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -46,8 +46,6 @@ */ static int tapeblock_open(struct block_device *, fmode_t); static int tapeblock_release(struct gendisk *, fmode_t); -static int tapeblock_ioctl(struct block_device *, fmode_t, unsigned int, - unsigned long); static int tapeblock_medium_changed(struct gendisk *); static int tapeblock_revalidate_disk(struct gendisk *); @@ -55,7 +53,6 @@ static const struct block_device_operations tapeblock_fops = { .owner = THIS_MODULE, .open = tapeblock_open, .release = tapeblock_release, - .ioctl = tapeblock_ioctl, .media_changed = tapeblock_medium_changed, .revalidate_disk = tapeblock_revalidate_disk, }; @@ -415,42 +412,6 @@ tapeblock_release(struct gendisk *disk, fmode_t mode) return 0; } -/* - * Support of some generic block device IOCTLs. - */ -static int -tapeblock_ioctl( - struct block_device * bdev, - fmode_t mode, - unsigned int command, - unsigned long arg -) { - int rc; - int minor; - struct gendisk *disk = bdev->bd_disk; - struct tape_device *device; - - rc = 0; - BUG_ON(!disk); - device = disk->private_data; - BUG_ON(!device); - minor = MINOR(bdev->bd_dev); - - DBF_LH(6, "tapeblock_ioctl(0x%0x)\n", command); - DBF_LH(6, "device = %d:%d\n", tapeblock_major, minor); - - switch (command) { - /* Refuse some IOCTL calls without complaining (mount). */ - case 0x5310: /* CDROMMULTISESSION */ - rc = -EINVAL; - break; - default: - rc = -EINVAL; - } - - return rc; -} - /* * Initialize block device frontend. */ -- cgit v1.2.3 From f8b068593db4a4184c8963fcd5a7f34584fde8ad Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:40 +0100 Subject: [S390] dasd: add proper compat pointer conversion for symmetrix ioctl Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 5819dc02a14..1c500c46222 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -2844,13 +2845,16 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) rc = -EFAULT; if (copy_from_user(&usrparm, argp, sizeof(usrparm))) goto out; -#ifndef CONFIG_64BIT - /* Make sure pointers are sane even on 31 bit. */ - if ((usrparm.psf_data >> 32) != 0 || (usrparm.rssd_result >> 32) != 0) { + if (is_compat_task() || sizeof(long) == 4) { + /* Make sure pointers are sane even on 31 bit. */ rc = -EINVAL; - goto out; + if ((usrparm.psf_data >> 32) != 0) + goto out; + if ((usrparm.rssd_result >> 32) != 0) + goto out; + usrparm.psf_data &= 0x7fffffffULL; + usrparm.rssd_result &= 0x7fffffffULL; } -#endif /* alloc I/O data area */ psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA); rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA); -- cgit v1.2.3 From 7b475d59a07cb193310afae48367bd1ea2faa411 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:41 +0100 Subject: [S390] con3215: remove empty ioctl function ...instead of adding a compat ioctl function which would do nothing as well. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/con3215.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 9d61683b563..59ec073724b 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -1036,22 +1036,6 @@ static void tty3215_flush_buffer(struct tty_struct *tty) tty_wakeup(tty); } -/* - * Currently we don't have any io controls for 3215 ttys - */ -static int tty3215_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - switch (cmd) { - default: - return -ENOIOCTLCMD; - } - return 0; -} - /* * Disable reading from a 3215 tty */ @@ -1117,7 +1101,6 @@ static const struct tty_operations tty3215_ops = { .write_room = tty3215_write_room, .chars_in_buffer = tty3215_chars_in_buffer, .flush_buffer = tty3215_flush_buffer, - .ioctl = tty3215_ioctl, .throttle = tty3215_throttle, .unthrottle = tty3215_unthrottle, .stop = tty3215_stop, -- cgit v1.2.3 From 0648f5659e2d51659bd8f42ff30f456775c3c12d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:43 +0100 Subject: [S390] zcrypt: add sanity check before copy_from_user() It's not obvious that copy_from_user() is called with a sane length parameter here. Even though it currently seems to be correct better add a check to prevent stack corruption / exploits. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/zcrypt_api.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 0d4d18bdd45..c68be24e27d 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -393,10 +393,12 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) * u_mult_inv > 128 bytes. */ if (copied == 0) { - int len; + unsigned int len; spin_unlock_bh(&zcrypt_device_lock); /* len is max 256 / 2 - 120 = 8 */ len = crt->inputdatalength / 2 - 120; + if (len > sizeof(z1)) + return -EFAULT; z1 = z2 = z3 = 0; if (copy_from_user(&z1, crt->np_prime, len) || copy_from_user(&z2, crt->bp_key, len) || -- cgit v1.2.3 From c5406079780f0f687316732353f49c3357504428 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 13 Jan 2010 20:44:44 +0100 Subject: [S390] tape_char: add missing compat_ptr conversion Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_char.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 2125ec7d95f..539045acaad 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -37,8 +38,9 @@ static ssize_t tapechar_write(struct file *, const char __user *, size_t, loff_t static int tapechar_open(struct inode *,struct file *); static int tapechar_release(struct inode *,struct file *); static long tapechar_ioctl(struct file *, unsigned int, unsigned long); -static long tapechar_compat_ioctl(struct file *, unsigned int, - unsigned long); +#ifdef CONFIG_COMPAT +static long tapechar_compat_ioctl(struct file *, unsigned int, unsigned long); +#endif static const struct file_operations tape_fops = { @@ -46,7 +48,9 @@ static const struct file_operations tape_fops = .read = tapechar_read, .write = tapechar_write, .unlocked_ioctl = tapechar_ioctl, +#ifdef CONFIG_COMPAT .compat_ioctl = tapechar_compat_ioctl, +#endif .open = tapechar_open, .release = tapechar_release, }; @@ -457,15 +461,22 @@ tapechar_ioctl(struct file *filp, unsigned int no, unsigned long data) return rc; } +#ifdef CONFIG_COMPAT static long tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) { struct tape_device *device = filp->private_data; int rval = -ENOIOCTLCMD; + unsigned long argp; + /* The 'arg' argument of any ioctl function may only be used for + * pointers because of the compat pointer conversion. + * Consider this when adding new ioctls. + */ + argp = (unsigned long) compat_ptr(data); if (device->discipline->ioctl_fn) { mutex_lock(&device->mutex); - rval = device->discipline->ioctl_fn(device, no, data); + rval = device->discipline->ioctl_fn(device, no, argp); mutex_unlock(&device->mutex); if (rval == -EINVAL) rval = -ENOIOCTLCMD; @@ -473,6 +484,7 @@ tapechar_compat_ioctl(struct file *filp, unsigned int no, unsigned long data) return rval; } +#endif /* CONFIG_COMPAT */ /* * Initialize character device frontend. -- cgit v1.2.3 From 1a647bd213d85c88507967104aea79b2649e6a6e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Wed, 13 Jan 2010 01:49:13 +0000 Subject: ixgbe: Do not attempt to perform interrupts in netpoll when down This patch resolves issues seen when running netconsole and rebooting via reboot -f. The issue was due to the fact that we were attempting to perform interrupt actions when the q_vectors and rings had already been freed via the ixgbe_shutdown routines. Signed-off-by: Alexander Duyck Acked-by: Mallikarjuna R Chilakala Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 2ad754c864c..385976709e7 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5576,6 +5576,10 @@ static void ixgbe_netpoll(struct net_device *netdev) struct ixgbe_adapter *adapter = netdev_priv(netdev); int i; + /* if interface is down do nothing */ + if (test_bit(__IXGBE_DOWN, &adapter->state)) + return; + adapter->flags |= IXGBE_FLAG_IN_NETPOLL; if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; -- cgit v1.2.3 From 8c47eaa76600cebc4869a42abb4568925ade6c47 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Wed, 13 Jan 2010 01:49:34 +0000 Subject: ixgbe: update copyright dates Signed-off-by: Shannon Nelson Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/Makefile | 2 +- drivers/net/ixgbe/ixgbe.h | 2 +- drivers/net/ixgbe/ixgbe_82598.c | 2 +- drivers/net/ixgbe/ixgbe_82599.c | 2 +- drivers/net/ixgbe/ixgbe_common.c | 2 +- drivers/net/ixgbe/ixgbe_common.h | 2 +- drivers/net/ixgbe/ixgbe_dcb.c | 2 +- drivers/net/ixgbe/ixgbe_dcb.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_82598.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_82599.c | 2 +- drivers/net/ixgbe/ixgbe_dcb_82599.h | 2 +- drivers/net/ixgbe/ixgbe_dcb_nl.c | 2 +- drivers/net/ixgbe/ixgbe_ethtool.c | 2 +- drivers/net/ixgbe/ixgbe_fcoe.c | 2 +- drivers/net/ixgbe/ixgbe_fcoe.h | 2 +- drivers/net/ixgbe/ixgbe_main.c | 4 ++-- drivers/net/ixgbe/ixgbe_phy.c | 2 +- drivers/net/ixgbe/ixgbe_phy.h | 2 +- drivers/net/ixgbe/ixgbe_type.h | 2 +- 20 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile index 21b41f42b61..bfef0ebcba9 100644 --- a/drivers/net/ixgbe/Makefile +++ b/drivers/net/ixgbe/Makefile @@ -1,7 +1,7 @@ ################################################################################ # # Intel 10 Gigabit PCI Express Linux driver -# Copyright(c) 1999 - 2009 Intel Corporation. +# Copyright(c) 1999 - 2010 Intel Corporation. # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 8da8eb53508..303e7bd39b6 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 204177d78ce..3103f416531 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index 538340527aa..b49bd6b9feb 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c index 688b8ca5da3..21f158f79dd 100644 --- a/drivers/net/ixgbe/ixgbe_common.c +++ b/drivers/net/ixgbe/ixgbe_common.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h index 27f3214bed2..dfff0ffaa50 100644 --- a/drivers/net/ixgbe/ixgbe_common.h +++ b/drivers/net/ixgbe/ixgbe_common.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c index a1562287342..9aea4f04bbd 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.c +++ b/drivers/net/ixgbe/ixgbe_dcb.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h index 64a9fa15c05..5caafd4afbc 100644 --- a/drivers/net/ixgbe/ixgbe_dcb.h +++ b/drivers/net/ixgbe/ixgbe_dcb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c index f30263898eb..f0e9279d466 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h index ebbe53c352a..cc728fa092e 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82598.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c index ec8a252636d..4f7a26ab411 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.c +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h index 9e5e2827e4a..0f3f791e1e1 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_82599.h +++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c index 3c7a79a7d7c..56f37f66b69 100644 --- a/drivers/net/ixgbe/ixgbe_dcb_nl.c +++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 0bd49d3b9f6..d77961fc75f 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index da32a108a7b..e9a20c88c15 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h index de8ff53187d..abf4b2b3f25 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.h +++ b/drivers/net/ixgbe/ixgbe_fcoe.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 385976709e7..9c9202f40b1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, @@ -52,7 +52,7 @@ static const char ixgbe_driver_string[] = #define DRV_VERSION "2.0.44-k2" const char ixgbe_driver_version[] = DRV_VERSION; -static char ixgbe_copyright[] = "Copyright (c) 1999-2009 Intel Corporation."; +static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation."; static const struct ixgbe_info *ixgbe_info_tbl[] = { [board_82598] = &ixgbe_82598_info, diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 9ecad17522c..1c1efd38695 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index 9b700f5bf1e..9cf5f3b4cc5 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 84650c6ebe0..9eafddfa1b9 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel 10 Gigabit PCI Express Linux driver - Copyright(c) 1999 - 2009 Intel Corporation. + Copyright(c) 1999 - 2010 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, -- cgit v1.2.3 From fddaa1aff881c98f524221236af98ce70dcd04cf Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 01:52:49 +0000 Subject: e1000e: MDIO slow mode should always be done for 82577 A previous 82577 workaround that set the MDIO access speed to slow mode for every PHY register read/write when the cable is unplugged should instead set the access mode to always be slow before any PHY register access. Since the mode bit gets cleared when the PHY is reset, set the mode after every PHY reset. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 1 - drivers/net/e1000e/ich8lan.c | 57 ++++++++++++++++++++++++++--- drivers/net/e1000e/phy.c | 85 -------------------------------------------- 3 files changed, 53 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cebbd9079d5..d6ee28f6ea0 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -582,7 +582,6 @@ extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); -extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow); extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); extern s32 e1000_check_polarity_82577(struct e1000_hw *hw); diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index ad08cf3f40c..c2ea8619750 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -138,6 +138,10 @@ #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ +/* KMRN Mode Control */ +#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) +#define HV_KMRN_MDIO_SLOW 0x0400 + /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ union ich8_hws_flash_status { @@ -219,6 +223,7 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); 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 inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) { @@ -270,7 +275,21 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->id = e1000_phy_unknown; - e1000e_get_phy_id(hw); + ret_val = e1000e_get_phy_id(hw); + if (ret_val) + goto out; + if ((phy->id == 0) || (phy->id == PHY_REVISION_MASK)) { + /* + * In case the PHY needs to be in mdio slow mode (eg. 82577), + * set slow mode and try to get the PHY id again. + */ + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) + goto out; + ret_val = e1000e_get_phy_id(hw); + if (ret_val) + goto out; + } phy->type = e1000e_get_phy_type_from_id(phy->id); switch (phy->type) { @@ -292,6 +311,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) break; } +out: return ret_val; } @@ -1075,6 +1095,26 @@ out: } +/** + * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode + * @hw: pointer to the HW structure + **/ +static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) +{ + s32 ret_val; + u16 data; + + ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data); + if (ret_val) + return ret_val; + + data |= HV_KMRN_MDIO_SLOW; + + ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data); + + return ret_val; +} + /** * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be * done after every PHY reset. @@ -1086,6 +1126,13 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) if (hw->mac.type != e1000_pchlan) return ret_val; + /* Set MDIO slow mode before any other MDIO access */ + if (hw->phy.type == e1000_phy_82577) { + ret_val = e1000_set_mdio_slow_mode_hv(hw); + if (ret_val) + goto out; + } + if (((hw->phy.type == e1000_phy_82577) && ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { @@ -1184,6 +1231,7 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) /* Allow time for h/w to get to a quiescent state after reset */ mdelay(10); + /* Perform any necessary post-reset workarounds */ if (hw->mac.type == e1000_pchlan) { ret_val = e1000_hv_phy_workarounds_ich8lan(hw); if (ret_val) @@ -2484,6 +2532,10 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) if (!ret_val) e1000_release_swflag_ich8lan(hw); + /* Perform any necessary post-reset workarounds */ + if (hw->mac.type == e1000_pchlan) + ret_val = e1000_hv_phy_workarounds_ich8lan(hw); + if (ctrl & E1000_CTRL_PHY_RST) ret_val = hw->phy.ops.get_cfg_done(hw); @@ -2528,9 +2580,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) kab |= E1000_KABGTXD_BGSQLBIAS; ew32(KABGTXD, kab); - if (hw->mac.type == e1000_pchlan) - ret_val = e1000_hv_phy_workarounds_ich8lan(hw); - out: return ret_val; } diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 55a2c0acfee..7f3ceb9dad6 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c @@ -152,32 +152,9 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw) if (phy->id != 0 && phy->id != PHY_REVISION_MASK) goto out; - /* - * If the PHY ID is still unknown, we may have an 82577 - * without link. We will try again after setting Slow MDIC - * mode. No harm in trying again in this case since the PHY - * ID is unknown at this point anyway. - */ - ret_val = phy->ops.acquire(hw); - if (ret_val) - goto out; - ret_val = e1000_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - phy->ops.release(hw); - retry_count++; } out: - /* Revert to MDIO fast mode, if applicable */ - if (retry_count) { - ret_val = phy->ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1000_set_mdio_slow_mode_hv(hw, false); - phy->ops.release(hw); - } - return ret_val; } @@ -2790,38 +2767,6 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active) return 0; } -/** - * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode - * @hw: pointer to the HW structure - * @slow: true for slow mode, false for normal mode - * - * Assumes semaphore already acquired. - **/ -s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) -{ - s32 ret_val = 0; - u16 data = 0; - - /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) - goto out; - - ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1, - (0x2180 | (slow << 10))); - if (ret_val) - goto out; - - /* dummy read when reverting to fast mode - throw away result */ - if (!slow) - ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); - -out: - return ret_val; -} - /** * __e1000_read_phy_reg_hv - Read HV PHY register * @hw: pointer to the HW structure @@ -2839,7 +2784,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); - bool in_slow_mode = false; if (!locked) { ret_val = hw->phy.ops.acquire(hw); @@ -2847,16 +2791,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, return ret_val; } - /* Workaround failure in MDIO access while cable is disconnected */ - if ((hw->phy.type == e1000_phy_82577) && - !(er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - - in_slow_mode = true; - } - /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, @@ -2893,10 +2827,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); out: - /* Revert to MDIO fast mode, if applicable */ - if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) - ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); - if (!locked) hw->phy.ops.release(hw); @@ -2948,7 +2878,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, s32 ret_val; u16 page = BM_PHY_REG_PAGE(offset); u16 reg = BM_PHY_REG_NUM(offset); - bool in_slow_mode = false; if (!locked) { ret_val = hw->phy.ops.acquire(hw); @@ -2956,16 +2885,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, return ret_val; } - /* Workaround failure in MDIO access while cable is disconnected */ - if ((hw->phy.type == e1000_phy_82577) && - !(er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000_set_mdio_slow_mode_hv(hw, true); - if (ret_val) - goto out; - - in_slow_mode = true; - } - /* Page 800 works differently than the rest so it has its own func */ if (page == BM_WUC_PAGE) { ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, @@ -3019,10 +2938,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, data); out: - /* Revert to MDIO fast mode, if applicable */ - if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) - ret_val |= e1000_set_mdio_slow_mode_hv(hw, false); - if (!locked) hw->phy.ops.release(hw); -- cgit v1.2.3 From baf86c9d36826fab0160251bbc87dfab3af48a21 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Wed, 13 Jan 2010 01:53:08 +0000 Subject: e1000e: workaround link issues on busy hub in half duplex on 82577/82578 This patch removes a delay in hardware after every received packet allowing more time for transmitted packets to go out in between received packets in half duplex. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index c2ea8619750..8b6ecd12788 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -1122,6 +1122,7 @@ static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) { s32 ret_val = 0; + u16 phy_data; if (hw->mac.type != e1000_pchlan) return ret_val; @@ -1165,16 +1166,32 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) hw->phy.addr = 1; ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); + hw->phy.ops.release(hw); if (ret_val) goto out; - hw->phy.ops.release(hw); /* * Configure the K1 Si workaround during phy reset assuming there is * link so that it disables K1 if link is in 1Gbps. */ ret_val = e1000_k1_gig_workaround_hv(hw, true); + if (ret_val) + goto out; + /* Workaround for link disconnects on a busy hub in half duplex */ + ret_val = hw->phy.ops.acquire(hw); + if (ret_val) + goto out; + ret_val = hw->phy.ops.read_reg_locked(hw, + PHY_REG(BM_PORT_CTRL_PAGE, 17), + &phy_data); + if (ret_val) + goto release; + ret_val = hw->phy.ops.write_reg_locked(hw, + PHY_REG(BM_PORT_CTRL_PAGE, 17), + phy_data & 0x00FF); +release: + hw->phy.ops.release(hw); out: return ret_val; } -- cgit v1.2.3 From 55029c1d65158aea9672c5dfadb43a57f23e3100 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Jan 2010 04:34:25 +0000 Subject: sfc: Fix polling for slow MCDI operations When the interface is down and we are using polled mode for MCDI operations, we busy-wait for completion for approximately 1 jiffy using udelay() and then back off to schedule(). But the completion will not wake the task, since we are using polled mode! We must use schedule_timeout_uninterruptible() instead. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/mcdi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index 683353b904c..0d4eba7266e 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c @@ -142,8 +142,9 @@ static int efx_mcdi_poll(struct efx_nic *efx) if (spins != 0) { --spins; udelay(1); - } else - schedule(); + } else { + schedule_timeout_uninterruptible(1); + } time = get_seconds(); -- cgit v1.2.3 From f3766c26a5d00189e5c0965c66f01956d15a92d6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 13 Jan 2010 10:59:13 +0000 Subject: sfc: Fix conditions for MDIO self-test The MDIO self-test should not be run on boards without an MDIO PHY, such as SFN5122F-R3 and later revisions. It should also not try to address a specific MMD in an MDIO clause 22 PHY. Check the mode_support field to decide which mode to use, if any. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/selftest.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index af393357979..250c8827b84 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -79,10 +79,14 @@ struct efx_loopback_state { static int efx_test_mdio(struct efx_nic *efx, struct efx_self_tests *tests) { int rc = 0; - int devad = __ffs(efx->mdio.mmds); + int devad; u16 physid1, physid2; - if (efx->phy_type == PHY_TYPE_NONE) + if (efx->mdio.mode_support & MDIO_SUPPORTS_C45) + devad = __ffs(efx->mdio.mmds); + else if (efx->mdio.mode_support & MDIO_SUPPORTS_C22) + devad = MDIO_DEVAD_NONE; + else return 0; mutex_lock(&efx->mac_lock); -- cgit v1.2.3 From 13fa95b0398d65885a79c6e95a09976ee9f8c009 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:36 +0000 Subject: tg3: Fix std prod ring nicaddr for 5787 and 57765 Commit 87668d352aa8d135bd695a050f18bbfc7b50b506, titled "tg3: Don't touch RCB nic addresses", tried to avoid assigning the nic address of the standard producer ring. Unfortunately, the default nic address is not correct for the 5787, the 5755M, or the 57765. This patch reenables the old behavior and opts out of the assignment only for the 5717. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Tested-by: Chow Loong Jin Tested-by: Dmitry Torokhov Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 3a74d216859..5c77e6a4870 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7742,7 +7742,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ((u64) tpr->rx_std_mapping >> 32)); tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW, ((u64) tpr->rx_std_mapping & 0xffffffff)); - if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_BUFFER_DESC); -- cgit v1.2.3 From 86cfe4ff02a51294cb2c974a8bedc7f648491df9 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:37 +0000 Subject: tg3: Fix std rx prod ring handling There are some tg3 devices that require the driver to post new rx buffers in smaller increments. Commit 4361935afe3abc3e5a93006b99197fac1fabbd50, "tg3: Consider rx_std_prod_idx a hw mailbox" changed how the driver tracks the rx producer ring updates, but it does not make any special considerations for the above-mentioned devices. For those devices, it is possible for the driver to hit the special case path, which updates the hardware mailbox register but skips updating the shadow software mailbox member. If the special case path represents the final mailbox update for this ISR iteration, the hardware and software mailbox values will be out of sync. Ultimately, this will cause the driver to use a stale mailbox value on the next iteration, which will appear to the hardware as a large rx buffer update. Bad things ensue. The fix is to update the software shadow mailbox member when the special case path is taken. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Reported-by: Dmitry Torokhov Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5c77e6a4870..4e8b87d1ffa 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4693,8 +4693,9 @@ next_pkt: (*post_ptr)++; if (unlikely(rx_std_posted >= tp->rx_std_max_post)) { - u32 idx = *post_ptr % TG3_RX_RING_SIZE; - tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx); + tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE; + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, + tpr->rx_std_prod_idx); work_mask &= ~RXD_OPAQUE_RING_STD; rx_std_posted = 0; } -- cgit v1.2.3 From d1ec96af77df611d1728f3bb70289f83a02df1ea Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:38 +0000 Subject: tg3: Add reliable serdes detection for 5717 A0 The serdes status bit does not work as intended for the 5717 A0. This patch implements an alternative detection scheme that will only be valid for A0 revisions. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 9 +++++++-- drivers/net/tg3.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 4e8b87d1ffa..0a632f96d16 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1037,7 +1037,11 @@ static void tg3_mdio_start(struct tg3 *tp) else tp->phy_addr = 1; - is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; + if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) + is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES; + else + is_serdes = tr32(TG3_CPMU_PHY_STRAP) & + TG3_CPMU_PHY_STRAP_IS_SERDES; if (is_serdes) tp->phy_addr += 7; } else @@ -12123,7 +12127,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->phy_id = eeprom_phy_id; if (eeprom_phy_serdes) { - if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) + if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) tp->tg3_flags2 |= TG3_FLG2_MII_SERDES; else tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index cd30889650f..43ed41b9f55 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1054,6 +1054,8 @@ #define CPMU_MUTEX_REQ_DRIVER 0x00001000 #define TG3_CPMU_MUTEX_GNT 0x00003660 #define CPMU_MUTEX_GNT_DRIVER 0x00001000 +#define TG3_CPMU_PHY_STRAP 0x00003664 +#define TG3_CPMU_PHY_STRAP_IS_SERDES 0x00000020 /* 0x3664 --> 0x3800 unused */ /* Mbuf cluster free registers */ -- cgit v1.2.3 From 55dffe79b34e2af98bd1315f1e00c2fc6a7a7078 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:39 +0000 Subject: tg3: Disable 5717 serdes and B0 support The B0 revision of the 5717 will not get enough testing by the time 2.6.33 ships. Since the kernel is already at RC3, serdes support will require too many patches to fix. For these reasons, this patch disables 5717 serdes support and will refuse to attach to all 5717 devices that are later than an A0 revision. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0a632f96d16..2d1a7404057 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -13390,6 +13390,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (err) return err; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 && + (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 || + (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))) + return -ENOTSUPP; + /* Initialize data/descriptor byte/word swapping. */ val = tr32(GRC_MODE); val &= GRC_MODE_HOST_STACKUP; -- cgit v1.2.3 From ba5b0bfa06b6fbee03c6889046e9adcefa5d2c20 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Tue, 12 Jan 2010 10:11:40 +0000 Subject: tg3: Update copyright and driver version This patch updates the copyright notice for 2010 and updates the version number to 3.106. Signed-off-by: Matt Carlson Reviewed-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 +++--- drivers/net/tg3.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 2d1a7404057..7f82b0238e0 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4,7 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. - * Copyright (C) 2005-2009 Broadcom Corporation. + * Copyright (C) 2005-2010 Broadcom Corporation. * * Firmware is: * Derived from proprietary unpublished source code, @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.105" -#define DRV_MODULE_RELDATE "December 2, 2009" +#define DRV_MODULE_VERSION "3.106" +#define DRV_MODULE_RELDATE "January 12, 2010" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 43ed41b9f55..8a167912902 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -4,6 +4,7 @@ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com) * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com) * Copyright (C) 2004 Sun Microsystems Inc. + * Copyright (C) 2007-2010 Broadcom Corporation. */ #ifndef _T3_H -- cgit v1.2.3 From a0e803a2112398150daa4d88c9d58409e0cf0b6c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 13 Jan 2010 12:09:08 +0100 Subject: iwmc3200wifi: Add UMAC wifi headers to the pmkid command Without this header, we can trigger a UMAC crash with debug enabled UMACs. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 4 ++++ drivers/net/wireless/iwmc3200wifi/commands.h | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 777584d76a8..1e41ad0fcad 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -973,6 +973,10 @@ int iwm_send_pmkid_update(struct iwm_priv *iwm, memset(&update, 0, sizeof(struct iwm_umac_pmkid_update)); + update.hdr.oid = UMAC_WIFI_IF_CMD_PMKID_UPDATE; + update.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_pmkid_update) - + sizeof(struct iwm_umac_wifi_if)); + update.command = cpu_to_le32(command); if (pmksa->bssid) memcpy(&update.bssid, pmksa->bssid, ETH_ALEN); diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 06af0552cd7..3dfd9f0e900 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -463,6 +463,7 @@ struct iwm_umac_cmd_stop_resume_tx { #define IWM_CMD_PMKID_FLUSH 3 struct iwm_umac_pmkid_update { + struct iwm_umac_wifi_if hdr; __le32 command; u8 bssid[ETH_ALEN]; __le16 reserved; -- cgit v1.2.3 From 75136d48e85915fd78a072f22897622b5d4c1814 Mon Sep 17 00:00:00 2001 From: Markus Pietrek Date: Fri, 15 Jan 2010 08:33:20 +0900 Subject: serial: sh-sci: using correct fifo size for SCIF and SCIFA ports. The sh-sci driver used the wrong fifosize for PORT_SCIFA and PORT_SCIF ports. If an incorrect size is used, the serial core will enforce an early shutdown on the port, especially with baudrates < 9600. Signed-off-by: Markus Pietrek Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 37f0de9dd9c..42f3333c4ad 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1052,7 +1052,18 @@ static void __devinit sci_init_single(struct platform_device *dev, sci_port->port.ops = &sci_uart_ops; sci_port->port.iotype = UPIO_MEM; sci_port->port.line = index; - sci_port->port.fifosize = 1; + + switch (p->type) { + case PORT_SCIFA: + sci_port->port.fifosize = 64; + break; + case PORT_SCIF: + sci_port->port.fifosize = 16; + break; + default: + sci_port->port.fifosize = 1; + break; + } if (dev) { sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; -- cgit v1.2.3 From 46759a7c132648d79121518d2f7c34edc3f0cf58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 10 Jan 2010 01:43:14 +0000 Subject: powerpc/macintosh: Make Open Firmware device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The match_table field of the struct of_device_id is constant in so it is worth to make the initialization data also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Benjamin Herrenschmidt --- drivers/macintosh/smu.c | 2 +- drivers/macintosh/therm_pm72.c | 2 +- drivers/macintosh/therm_windtunnel.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 96faa799b82..f96feeb6b9c 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -660,7 +660,7 @@ static int smu_platform_probe(struct of_device* dev, return 0; } -static struct of_device_id smu_platform_match[] = +static const struct of_device_id smu_platform_match[] = { { .type = "smu", diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index ea32c7e5a9a..454bc501df3 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -2211,7 +2211,7 @@ static int fcu_of_remove(struct of_device* dev) return 0; } -static struct of_device_id fcu_match[] = +static const struct of_device_id fcu_match[] = { { .type = "fcu", diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 3fbe41b0ac0..ba48fd76396 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c @@ -457,7 +457,7 @@ therm_of_remove( struct of_device *dev ) return 0; } -static struct of_device_id therm_of_match[] = {{ +static const struct of_device_id therm_of_match[] = {{ .name = "fan", .compatible = "adm1030" }, {} -- cgit v1.2.3 From 02ab851324dc7e2fc75787f7fae71187092be7ed Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sun, 10 Jan 2010 17:51:42 +0000 Subject: serial/pmac_zilog: Workaround problem due to interrupt on closed port It seems that in qemu, we can see an interrupt in R3 despite the fact that it's masked in W1. The chip doesn't actually issue an interrupt, but we can "see" it when taking an interrupt for the other channel. This may be a qemu bug ... or not, so let's be safe and avoid calling into the UART layer when that happens which woulc cause a crash. Signed-off-by: Benjamin Herrenschmidt Acked-by: Rob Landley --- drivers/serial/pmac_zilog.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 0700cd10b97..683e66f18e8 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -411,6 +411,17 @@ static void pmz_transmit_chars(struct uart_pmac_port *uap) goto ack_tx_int; } + /* Under some circumstances, we see interrupts reported for + * a closed channel. The interrupt mask in R1 is clear, but + * R3 still signals the interrupts and we see them when taking + * an interrupt for the other channel (this could be a qemu + * bug but since the ESCC doc doesn't specify precsiely whether + * R3 interrup status bits are masked by R1 interrupt enable + * bits, better safe than sorry). --BenH. + */ + if (!ZS_IS_OPEN(uap)) + goto ack_tx_int; + if (uap->port.x_char) { uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; write_zsdata(uap, uap->port.x_char); -- cgit v1.2.3 From aa8b83cb0b48e3cac58a3b75ad9c556564c5fe9d Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Fri, 25 Sep 2009 03:31:43 +0000 Subject: powerpc/hvc: Driver build breaks with !HVC_CONSOLE Hi Stephen, next-20090925 randconfig build breaks on hvcs driver on powerpc, with HVC_CONSOLE=n. ERROR: ".hvc_put_chars" [drivers/char/hvcs.ko] undefined! ERROR: ".hvc_get_chars" [drivers/char/hvcs.ko] undefined! adding the dependency of HVC_CONSOLE helped Signed-off-by: Kamalesh Babulal Signed-off-by: Benjamin Herrenschmidt --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 31be3ac2e21..e023682be2c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -669,7 +669,7 @@ config VIRTIO_CONSOLE config HVCS tristate "IBM Hypervisor Virtual Console Server support" - depends on PPC_PSERIES + depends on PPC_PSERIES && HVC_CONSOLE help Partitionable IBM Power5 ppc64 machines allow hosting of firmware virtual consoles from one Linux partition by -- cgit v1.2.3 From 926311fd7dabcd284a1e8a87a3e2bb5f929c0c60 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Mon, 11 Jan 2010 20:58:21 +0100 Subject: amd64_edac: Ensure index stays within bounds in amd64_get_scrub_rate Add a missing iterator variable thus fixing the conditional of the for-loop in amd64_get_scrub_rate(). Signed-off-by: Roel Kluin Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c5facd951dd..000dc67b85b 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -197,7 +197,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) edac_printk(KERN_DEBUG, EDAC_MC, "pci-read, sdram scrub control value: %d \n", scrubval); - for (i = 0; ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { if (scrubrates[i].scrubval == scrubval) { *bw = scrubrates[i].bandwidth; status = 0; -- cgit v1.2.3 From c7c85101afd0cb8ce497456d12ee1cad4aad152f Mon Sep 17 00:00:00 2001 From: Zou Nan hai Date: Fri, 15 Jan 2010 10:29:06 +0800 Subject: drm/i915: remove loop in Ironlake interrupt handler On Ironlake, there is an interrupt master control bit. With the bit disabled before clearing IIR, we do not need to handle extra interrupt in a loop. This patch removes the loop in Ironlake interrupt handler. It fixed irq lost issue on some Ironlake platforms. Cc: Stable Team Signed-off-by: Zou Nan hai Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_irq.c | 68 ++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7cd8110051b..89a071a3e6f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -274,7 +274,6 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; u32 de_iir, gt_iir, de_ier, pch_iir; - u32 new_de_iir, new_gt_iir, new_pch_iir; struct drm_i915_master_private *master_priv; /* disable master interrupt before clearing iir */ @@ -286,51 +285,42 @@ irqreturn_t ironlake_irq_handler(struct drm_device *dev) gt_iir = I915_READ(GTIIR); pch_iir = I915_READ(SDEIIR); - for (;;) { - if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) - break; - - ret = IRQ_HANDLED; + if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) + goto done; - /* should clear PCH hotplug event before clear CPU irq */ - I915_WRITE(SDEIIR, pch_iir); - new_pch_iir = I915_READ(SDEIIR); + ret = IRQ_HANDLED; - I915_WRITE(DEIIR, de_iir); - new_de_iir = I915_READ(DEIIR); - I915_WRITE(GTIIR, gt_iir); - new_gt_iir = I915_READ(GTIIR); - - if (dev->primary->master) { - master_priv = dev->primary->master->driver_priv; - if (master_priv->sarea_priv) - master_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); - } - - if (gt_iir & GT_USER_INTERRUPT) { - u32 seqno = i915_get_gem_seqno(dev); - dev_priv->mm.irq_gem_seqno = seqno; - trace_i915_gem_request_complete(dev, seqno); - DRM_WAKEUP(&dev_priv->irq_queue); - dev_priv->hangcheck_count = 0; - mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); - } + if (dev->primary->master) { + master_priv = dev->primary->master->driver_priv; + if (master_priv->sarea_priv) + master_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); + } - if (de_iir & DE_GSE) - ironlake_opregion_gse_intr(dev); + if (gt_iir & GT_USER_INTERRUPT) { + u32 seqno = i915_get_gem_seqno(dev); + dev_priv->mm.irq_gem_seqno = seqno; + trace_i915_gem_request_complete(dev, seqno); + DRM_WAKEUP(&dev_priv->irq_queue); + dev_priv->hangcheck_count = 0; + mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); + } - /* check event from PCH */ - if ((de_iir & DE_PCH_EVENT) && - (pch_iir & SDE_HOTPLUG_MASK)) { - queue_work(dev_priv->wq, &dev_priv->hotplug_work); - } + if (de_iir & DE_GSE) + ironlake_opregion_gse_intr(dev); - de_iir = new_de_iir; - gt_iir = new_gt_iir; - pch_iir = new_pch_iir; + /* check event from PCH */ + if ((de_iir & DE_PCH_EVENT) && + (pch_iir & SDE_HOTPLUG_MASK)) { + queue_work(dev_priv->wq, &dev_priv->hotplug_work); } + /* should clear PCH hotplug event before clear CPU irq */ + I915_WRITE(SDEIIR, pch_iir); + I915_WRITE(GTIIR, gt_iir); + I915_WRITE(DEIIR, de_iir); + +done: I915_WRITE(DEIER, de_ier); (void)I915_READ(DEIER); -- cgit v1.2.3 From 6036ae7e9486352d5d1cbbee89186986e28e11fd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 15 Jan 2010 13:04:48 -0800 Subject: drm/i915: Remove chatty execbuf failure message. Suggested-by: Chris Wilson > Acked-by: Jesse Barnes (in principle) Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0f4afa3b03f..0c67924ca80 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4051,8 +4051,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, "back to user (%d)\n", args->buffer_count, ret); } - } else { - DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); } drm_free_large(exec_list); -- cgit v1.2.3 From 21bd770b9c90ee6a53a9dbb6293513a8c7654cfe Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 13 Jan 2010 14:10:50 +0000 Subject: drm/i915: Fix the incorrect cursor A bit definition in DSPFW2 register Signed-off-by: Zhao Yakui Reviewed-by: Eric Anholt Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 149d360d64a..847006c5218 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1815,7 +1815,7 @@ #define DSPFW_PLANEB_SHIFT 8 #define DSPFW2 0x70038 #define DSPFW_CURSORA_MASK 0x00003f00 -#define DSPFW_CURSORA_SHIFT 16 +#define DSPFW_CURSORA_SHIFT 8 #define DSPFW3 0x7003c #define DSPFW_HPLL_SR_EN (1<<31) #define DSPFW_CURSOR_SR_SHIFT 24 -- cgit v1.2.3 From 33814341f22f13cec17e8d7fbf6f7e8000e3efa4 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 14 Jan 2010 20:48:02 +0000 Subject: drm/i915: disable LVDS downclock by default Many platform support this feature, and it can provide significant power savings when the reduced refresh rate is low. However, on some platforms a secondary (reduced) timing is provided but not actually supported by the hardware. This results in undesirable flicker at runtime. So disable the feature by default, but allow users to opt-in to the reduced clock behavior with a new module parameter, lvds_downclock, that can be set to 1 to enable the feature. Signed-off-by: Jesse Barnes Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 3 ++- drivers/gpu/drm/i915/intel_lvds.c | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 66f7bac2ee5..46d88965852 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -45,6 +45,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); unsigned int i915_powersave = 1; module_param_named(powersave, i915_powersave, int, 0400); +unsigned int i915_lvds_downclock = 0; +module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); + static struct drm_driver driver; #define INTEL_VGA_DEVICE(id, info) { \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 445c49c6c39..5f781a74bf5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -722,6 +722,7 @@ extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc; extern unsigned int i915_powersave; +extern unsigned int i915_lvds_downclock; extern void i915_save_display(struct drm_device *dev); extern void i915_restore_display(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f2756774758..b53c46f202f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -197,7 +197,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, memset(temp_mode, 0, sizeof(*temp_mode)); } kfree(temp_mode); - if (temp_downclock < panel_fixed_mode->clock) { + if (temp_downclock < panel_fixed_mode->clock && + i915_lvds_downclock) { dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; DRM_DEBUG_KMS("LVDS downclock is found in VBT. ", diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 5041590dfdc..aa74e59bec6 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -926,7 +926,8 @@ static void intel_find_lvds_downclock(struct drm_device *dev, } } mutex_unlock(&dev->mode_config.mutex); - if (temp_downclock < panel_fixed_mode->clock) { + if (temp_downclock < panel_fixed_mode->clock && + i915_lvds_downclock) { /* We found the downclock for LVDS. */ dev_priv->lvds_downclock_avail = 1; dev_priv->lvds_downclock = temp_downclock; -- cgit v1.2.3 From 500a8cc466a24e2fbc4c86ef9c6467ae2ffdeb0c Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Wed, 13 Jan 2010 11:19:52 +0800 Subject: drm/i915: parse eDP panel color depth from VBT block Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 32 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_bios.h | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5f781a74bf5..2c1669488b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -283,6 +283,7 @@ typedef struct drm_i915_private { unsigned int lvds_use_ssc:1; unsigned int edp_support:1; int lvds_ssc_freq; + int edp_bpp; struct notifier_block lid_notifier; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b53c46f202f..15fbc1b5a83 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -33,6 +33,8 @@ #define SLAVE_ADDR1 0x70 #define SLAVE_ADDR2 0x72 +static int panel_type; + static void * find_section(struct bdb_header *bdb, int section_id) { @@ -128,6 +130,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, dev_priv->lvds_dither = lvds_options->pixel_dither; if (lvds_options->panel_type == 0xff) return; + panel_type = lvds_options->panel_type; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) @@ -405,6 +408,34 @@ parse_driver_features(struct drm_i915_private *dev_priv, dev_priv->render_reclock_avail = true; } +static void +parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) +{ + struct bdb_edp *edp; + + edp = find_section(bdb, BDB_EDP); + if (!edp) { + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp_support) { + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported,\ + assume 18bpp panel color depth.\n"); + dev_priv->edp_bpp = 18; + } + return; + } + + switch ((edp->color_depth >> (panel_type * 2)) & 3) { + case EDP_18BPP: + dev_priv->edp_bpp = 18; + break; + case EDP_24BPP: + dev_priv->edp_bpp = 24; + break; + case EDP_30BPP: + dev_priv->edp_bpp = 30; + break; + } +} + static void parse_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -522,6 +553,7 @@ intel_init_bios(struct drm_device *dev) parse_sdvo_device_mapping(dev_priv, bdb); parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); + parse_edp(dev_priv, bdb); pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 425ac9d7f72..4c18514f6f8 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -98,6 +98,7 @@ struct vbios_data { #define BDB_SDVO_LVDS_PNP_IDS 24 #define BDB_SDVO_LVDS_POWER_SEQ 25 #define BDB_TV_OPTIONS 26 +#define BDB_EDP 27 #define BDB_LVDS_OPTIONS 40 #define BDB_LVDS_LFP_DATA_PTRS 41 #define BDB_LVDS_LFP_DATA 42 @@ -426,6 +427,45 @@ struct bdb_driver_features { u8 custom_vbt_version; } __attribute__((packed)); +#define EDP_18BPP 0 +#define EDP_24BPP 1 +#define EDP_30BPP 2 +#define EDP_RATE_1_62 0 +#define EDP_RATE_2_7 1 +#define EDP_LANE_1 0 +#define EDP_LANE_2 1 +#define EDP_LANE_4 3 +#define EDP_PREEMPHASIS_NONE 0 +#define EDP_PREEMPHASIS_3_5dB 1 +#define EDP_PREEMPHASIS_6dB 2 +#define EDP_PREEMPHASIS_9_5dB 3 +#define EDP_VSWING_0_4V 0 +#define EDP_VSWING_0_6V 1 +#define EDP_VSWING_0_8V 2 +#define EDP_VSWING_1_2V 3 + +struct edp_power_seq { + u16 t3; + u16 t7; + u16 t9; + u16 t10; + u16 t12; +} __attribute__ ((packed)); + +struct edp_link_params { + u8 rate:4; + u8 lanes:4; + u8 preemphasis:4; + u8 vswing:4; +} __attribute__ ((packed)); + +struct bdb_edp { + struct edp_power_seq power_seqs[16]; + u32 color_depth; + u32 sdrrs_msa_timing_delay; + struct edp_link_params link_params[16]; +} __attribute__ ((packed)); + bool intel_init_bios(struct drm_device *dev); /* -- cgit v1.2.3 From 885a5fb5b120a5c7e0b3baad7b0feb5a89f76c18 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 12 Jan 2010 05:38:31 +0800 Subject: drm/i915: fix pixel color depth setting on eDP Original DP mode_valid check didn't take pixel color depth into account, which made one 1600x900 eDP panel's mode check invalid because of overclock, but actually this 6bpc panel does can work with x1 lane at 2.7G. This one trys to take bpp value properly both in mode validation and mode setting. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 16 ++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4b96a54b8e4..45da78ef4a9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2924,6 +2924,21 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, temp |= PIPE_8BPC; else temp |= PIPE_6BPC; + } else if (is_edp) { + switch (dev_priv->edp_bpp/3) { + case 8: + temp |= PIPE_8BPC; + break; + case 10: + temp |= PIPE_10BPC; + break; + case 6: + temp |= PIPE_6BPC; + break; + case 12: + temp |= PIPE_12BPC; + break; + } } else temp |= PIPE_8BPC; I915_WRITE(pipeconf_reg, temp); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0ec07e43d6c..184b6780c44 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -125,9 +125,15 @@ intel_dp_link_clock(uint8_t link_bw) /* I think this is a fiction */ static int -intel_dp_link_required(int pixel_clock) +intel_dp_link_required(struct drm_device *dev, + struct intel_output *intel_output, int pixel_clock) { - return pixel_clock * 3; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (IS_eDP(intel_output)) + return (pixel_clock * dev_priv->edp_bpp) / 8; + else + return pixel_clock * 3; } static int @@ -138,7 +144,8 @@ intel_dp_mode_valid(struct drm_connector *connector, int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); int max_lanes = intel_dp_max_lane_count(intel_output); - if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) + if (intel_dp_link_required(connector->dev, intel_output, mode->clock) + > max_link_clock * max_lanes) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -492,7 +499,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, for (clock = 0; clock <= max_clock; clock++) { int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; - if (intel_dp_link_required(mode->clock) <= link_avail) { + if (intel_dp_link_required(encoder->dev, intel_output, mode->clock) + <= link_avail) { dp_priv->link_bw = bws[clock]; dp_priv->lane_count = lane_count; adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); -- cgit v1.2.3 From 6251ec0ae2eb9e9e96689422358c2fdb35c63768 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 12 Jan 2010 05:38:32 +0800 Subject: drm/i915: fix eDP pipe mask eDP could be on pipe A or B. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/intel_dp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 184b6780c44..439506cefc1 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1331,11 +1331,10 @@ intel_dp_init(struct drm_device *dev, int output_reg) else if (output_reg == DP_D || output_reg == PCH_DP_D) intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); - if (IS_eDP(intel_output)) { - intel_output->crtc_mask = (1 << 1); + if (IS_eDP(intel_output)) intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT); - } else - intel_output->crtc_mask = (1 << 0) | (1 << 1); + + intel_output->crtc_mask = (1 << 0) | (1 << 1); connector->interlace_allowed = true; connector->doublescan_allowed = 0; -- cgit v1.2.3 From 9b974cc17166d31afed2638d56bdbf9829afbfaa Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Tue, 5 Jan 2010 11:25:06 +0800 Subject: drm/i915: enable 36bit physical address for hardware status page This enables possible 36bit address mask on 965G that use physical address for hw status page. Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt --- drivers/char/agp/intel-agp.c | 6 +++++- drivers/gpu/drm/i915/i915_dma.c | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 30c36ac2cd0..3999a5f25f3 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -2460,10 +2460,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, &bridge->mode); } - if (bridge->driver->mask_memory == intel_i965_mask_memory) + if (bridge->driver->mask_memory == intel_i965_mask_memory) { if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36))) dev_err(&intel_private.pcidev->dev, "set gfx device dma mask 36bit failed!\n"); + else + pci_set_consistent_dma_mask(intel_private.pcidev, + DMA_BIT_MASK(36)); + } pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bbe47812e4b..e660ac07f3b 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -134,6 +134,10 @@ static int i915_init_phys_hws(struct drm_device *dev) memset(dev_priv->hw_status_page, 0, PAGE_SIZE); + if (IS_I965G(dev)) + dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & + 0xf0; + I915_WRITE(HWS_PGA, dev_priv->dma_status_page); DRM_DEBUG_DRIVER("Enabled hardware status page\n"); return 0; -- cgit v1.2.3 From f5347867c5aea94c625246eaff8f7820b0a4cd8a Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:03 +0300 Subject: ACPI: SBS: Move SBS HC callback to faster Notify queue SBS transactions should happen in Notify work queue, to not create a dead lock with GPE execution accessing SBS devices. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- drivers/acpi/sbshc.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 9cc38857c33..04733092982 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -535,7 +535,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec) return -ENOMEM; memcpy(copy, handler, sizeof(*copy)); pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); - return acpi_os_execute(OSL_GPE_HANDLER, + return acpi_os_execute((copy->func) ? + OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, acpi_ec_run, copy); } } diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d9339806df4..fd09229282e 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -242,7 +242,7 @@ static int smbus_alarm(void *context) case ACPI_SBS_CHARGER: case ACPI_SBS_MANAGER: case ACPI_SBS_BATTERY: - acpi_os_execute(OSL_GPE_HANDLER, + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_smbus_callback, hc); default:; } -- cgit v1.2.3 From 54070101f86ca9a6e9ba243c999d144721ec3db7 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 30 Dec 2009 15:53:10 +0300 Subject: ACPI: EC: Add wait for irq storm Merge of poll and irq modes accelerated EC transaction, so that keyboard starts to suffer again. Add msleep(1) into transaction path for the storm to allow keyboard controller to do its job. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14747 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 04733092982..d6471bb6852 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -259,7 +259,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); ret = ec_poll(ec); - pr_debug(PREFIX "transaction end\n"); spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); @@ -316,6 +315,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) /* check if we received SCI during transaction */ ec_check_sci_sync(ec, acpi_ec_read_status(ec)); if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + msleep(1); /* it is safe to enable GPE outside of transaction */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { @@ -323,6 +323,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } + pr_debug(PREFIX "transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); -- cgit v1.2.3 From 6a4e2b7503d1f630bface040cf0f5a7aac1fabdb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Fri, 8 Jan 2010 21:29:58 +0800 Subject: ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes If the BIOS pokes the system-wide OSC bits to see if Linux supports evaluating _OST after a _PPC change notification, answer yes. Also, fix an oversight where we neglected to set the OSC bit advertising processor aggregator device support when acpi-pad is compiled as a module. Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cf761b904e4..a52126e4630 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void) capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ -#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR +#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ + defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif + +#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) + capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; +#endif if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) -- cgit v1.2.3 From 070a24f4d238612bede515023893b18f494774c4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 8 Jan 2010 11:12:41 -0700 Subject: ACPI: Remove unnecessary cast. The struct seq_file 'private' member is a void *, the cast is not needed. Also, remove an extra whitespace line. Signed-off-by: H Hartley Sweeten Signed-off-by: Len Brown --- drivers/acpi/processor_thermal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 140c5c5b423..6deafb4aa0d 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { #ifdef CONFIG_ACPI_PROCFS static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = (struct acpi_processor *)seq->private; - + struct acpi_processor *pr = seq->private; if (!pr) goto end; -- cgit v1.2.3 From da8ba01deb98f3dc0558b1f5a37e64f40bba7904 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 6 Jan 2010 22:07:37 +0100 Subject: eeepc-laptop: disable cpu speed control on EeePC 701 The EeePC 4G ("701") implements CFVS, but it is not supported by the pre-installed OS, and the original option to change it in the BIOS setup screen was removed in later versions. Judging by the lack of "Super Hybrid Engine" on Asus product pages, this applies to all "701" models (4G/4G Surf/2G Surf). So Asus made a deliberate decision not to support it on this model. We have several reports that using it can cause the system to hang [1]. That said, it does not happen all the time. Some users do not experience it at all (and apparently wish to continue "right-clocking"). Check for the EeePC 701 using DMI. If met, then disable writes to the "cpufv" sysfs attribute and log an explanatory message. Add a "cpufv_disabled" attribute which allow users to override this policy. Writing to this attribute will log a second message. The sysfs attribute is more useful than a module option, because it makes it easier for userspace scripts to provide consistent behaviour (according to user configuration), regardless of whether the kernel includes this change. [1] Signed-off-by: Alan Jenkins Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5838c69b2fb..e954f2af572 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -35,6 +35,7 @@ #include #include #include +#include #define EEEPC_LAPTOP_VERSION "0.1" #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" @@ -159,6 +160,7 @@ struct eeepc_laptop { acpi_handle handle; /* the handle of the acpi device */ u32 cm_supported; /* the control methods supported by this BIOS */ + bool cpufv_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev, struct eeepc_cpufv c; int rv, value; + if (eeepc->cpufv_disabled) + return -EPERM; if (get_cpufv(eeepc, &c)) return -ENODEV; rv = parse_arg(buf, count, &value); @@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev, return rv; } +static ssize_t show_cpufv_disabled(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", eeepc->cpufv_disabled); +} + +static ssize_t store_cpufv_disabled(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); + int rv, value; + + rv = parse_arg(buf, count, &value); + if (rv < 0) + return rv; + + switch (value) { + case 0: + if (eeepc->cpufv_disabled) + pr_warning("cpufv enabled (not officially supported " + "on this model)\n"); + eeepc->cpufv_disabled = false; + return rv; + case 1: + return -EPERM; + default: + return -EINVAL; + } +} + + static struct device_attribute dev_attr_cpufv = { .attr = { .name = "cpufv", @@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = { .show = show_available_cpufv }; +static struct device_attribute dev_attr_cpufv_disabled = { + .attr = { + .name = "cpufv_disabled", + .mode = 0644 }, + .show = show_cpufv_disabled, + .store = store_cpufv_disabled +}; + + static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_disp.attr, &dev_attr_cpufv.attr, &dev_attr_available_cpufv.attr, + &dev_attr_cpufv_disabled.attr, NULL }; @@ -1261,6 +1310,42 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) } } +static void eeepc_dmi_check(struct eeepc_laptop *eeepc) +{ + const char *model; + + /* + * Blacklist for setting cpufv (cpu speed). + * + * EeePC 4G ("701") implements CFVS, but it is not supported + * by the pre-installed OS, and the original option to change it + * in the BIOS setup screen was removed in later versions. + * + * Judging by the lack of "Super Hybrid Engine" on Asus product pages, + * this applies to all "701" models (4G/4G Surf/2G Surf). + * + * So Asus made a deliberate decision not to support it on this model. + * We have several reports that using it can cause the system to hang + * + * The hang has also been reported on a "702" (Model name "8G"?). + * + * We avoid dmi_check_system() / dmi_match(), because they use + * substring matching. We don't want to affect the "701SD" + * and "701SDX" models, because they do support S.H.E. + */ + + model = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!model) + return; + + if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { + eeepc->cpufv_disabled = true; + pr_info("model %s does not officially support setting cpu " + "speed\n", model); + pr_info("cpufv disabled to avoid instability\n"); + } +} + static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) { int dummy; @@ -1342,6 +1427,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; + eeepc_dmi_check(eeepc); + result = eeepc_acpi_init(eeepc, device); if (result) goto fail_platform; -- cgit v1.2.3 From 10ae4b5663ff3092553bfbd867e7bd474ce6c553 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:38 +0100 Subject: eeepc-laptop: dmi blacklist to disable pci hotplug code This is a short term workaround for Eeepc 1005HA. refs: Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index e954f2af572..7fc944ac207 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -161,6 +161,7 @@ struct eeepc_laptop { u32 cm_supported; /* the control methods supported by this BIOS */ bool cpufv_disabled; + bool hotplug_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -845,6 +846,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) if (result && result != -ENODEV) goto exit; + if (eeepc->hotplug_disabled) + return 0; + result = eeepc_setup_pci_hotplug(eeepc); /* * If we get -EBUSY then something else is handling the PCI hotplug - @@ -1314,6 +1318,10 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) { const char *model; + model = dmi_get_system_info(DMI_PRODUCT_NAME); + if (!model) + return; + /* * Blacklist for setting cpufv (cpu speed). * @@ -1333,17 +1341,24 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * substring matching. We don't want to affect the "701SD" * and "701SDX" models, because they do support S.H.E. */ - - model = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!model) - return; - if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { eeepc->cpufv_disabled = true; pr_info("model %s does not officially support setting cpu " "speed\n", model); pr_info("cpufv disabled to avoid instability\n"); } + + /* + * Blacklist for wlan hotplug + * + * Eeepc 1005HA doesn't work like others models and don't need the + * hotplug code. In fact, current hotplug code seems to unplug another + * device... + */ + if (strcmp(model, "1005HA") == 0) { + eeepc->hotplug_disabled = true; + pr_info("wlan hotplug disabled\n"); + } } static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name) -- cgit v1.2.3 From 642e0447cb910ceabae0b4ea6c0cd3449d5c5abb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 6 Jan 2010 22:07:39 +0100 Subject: eeepc-laptop: switch to using sparse keymap library Signed-off-by: Dmitry Torokhov Tested-by: Alan Jenkins Acked-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 1 + drivers/platform/x86/eeepc-laptop.c | 186 ++++++++++-------------------------- 2 files changed, 52 insertions(+), 135 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index db32c25e360..f526e735c5a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -364,6 +364,7 @@ config EEEPC_LAPTOP select HWMON select LEDS_CLASS select NEW_LEDS + select INPUT_SPARSEKMAP ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 7fc944ac207..07d7978c558 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -121,38 +122,28 @@ static const char *cm_setv[] = { NULL, NULL, "PBPS", "TPDS" }; -struct key_entry { - char type; - u8 code; - u16 keycode; -}; - -enum { KE_KEY, KE_END }; - static const struct key_entry eeepc_keymap[] = { - /* Sleep already handled via generic ACPI code */ - {KE_KEY, 0x10, KEY_WLAN }, - {KE_KEY, 0x11, KEY_WLAN }, - {KE_KEY, 0x12, KEY_PROG1 }, - {KE_KEY, 0x13, KEY_MUTE }, - {KE_KEY, 0x14, KEY_VOLUMEDOWN }, - {KE_KEY, 0x15, KEY_VOLUMEUP }, - {KE_KEY, 0x16, KEY_DISPLAY_OFF }, - {KE_KEY, 0x1a, KEY_COFFEE }, - {KE_KEY, 0x1b, KEY_ZOOM }, - {KE_KEY, 0x1c, KEY_PROG2 }, - {KE_KEY, 0x1d, KEY_PROG3 }, - {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, - {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, - {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, - {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ - {KE_KEY, 0x38, KEY_F14 }, - {KE_END, 0}, + { KE_KEY, 0x10, { KEY_WLAN } }, + { KE_KEY, 0x11, { KEY_WLAN } }, + { KE_KEY, 0x12, { KEY_PROG1 } }, + { KE_KEY, 0x13, { KEY_MUTE } }, + { KE_KEY, 0x14, { KEY_VOLUMEDOWN } }, + { KE_KEY, 0x15, { KEY_VOLUMEUP } }, + { KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, + { KE_KEY, 0x1a, { KEY_COFFEE } }, + { KE_KEY, 0x1b, { KEY_ZOOM } }, + { KE_KEY, 0x1c, { KEY_PROG2 } }, + { KE_KEY, 0x1d, { KEY_PROG3 } }, + { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } }, + { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } }, + { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, + { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ + { KE_KEY, 0x38, { KEY_F14 } }, + { KE_END, 0 }, }; - /* * This is the main structure, we can use it to store useful information */ @@ -1143,120 +1134,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) /* * Input device (i.e. hotkeys) */ -static struct key_entry *eeepc_get_entry_by_scancode( - struct eeepc_laptop *eeepc, - int code) +static int eeepc_input_init(struct eeepc_laptop *eeepc) { - struct key_entry *key; - - for (key = eeepc->keymap; key->type != KE_END; key++) - if (code == key->code) - return key; + struct input_dev *input; + int error; - return NULL; -} - -static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) -{ - static struct key_entry *key; - - key = eeepc_get_entry_by_scancode(eeepc, event); - if (key) { - switch (key->type) { - case KE_KEY: - input_report_key(eeepc->inputdev, key->keycode, - 1); - input_sync(eeepc->inputdev); - input_report_key(eeepc->inputdev, key->keycode, - 0); - input_sync(eeepc->inputdev); - break; - } + input = input_allocate_device(); + if (!input) { + pr_info("Unable to allocate input device\n"); + return -ENOMEM; } -} - -static struct key_entry *eeepc_get_entry_by_keycode( - struct eeepc_laptop *eeepc, int code) -{ - struct key_entry *key; - - for (key = eeepc->keymap; key->type != KE_END; key++) - if (code == key->keycode && key->type == KE_KEY) - return key; - return NULL; -} + input->name = "Asus EeePC extra buttons"; + input->phys = EEEPC_LAPTOP_FILE "/input0"; + input->id.bustype = BUS_HOST; + input->dev.parent = &eeepc->platform_device->dev; -static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) -{ - struct eeepc_laptop *eeepc = input_get_drvdata(dev); - struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); - - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; + error = sparse_keymap_setup(input, eeepc_keymap, NULL); + if (error) { + pr_err("Unable to setup input device keymap\n"); + goto err_free_dev; } - return -EINVAL; -} - -static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ - struct eeepc_laptop *eeepc = input_get_drvdata(dev); - struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = eeepc_get_entry_by_scancode(eeepc, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + error = input_register_device(input); + if (error) { + pr_err("Unable to register input device\n"); + goto err_free_keymap; } - return -EINVAL; -} - -static int eeepc_input_init(struct eeepc_laptop *eeepc) -{ - const struct key_entry *key; - int result; - - eeepc->inputdev = input_allocate_device(); - if (!eeepc->inputdev) { - pr_info("Unable to allocate input device\n"); - return -ENOMEM; - } - eeepc->inputdev->name = "Asus EeePC extra buttons"; - eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; - eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; - eeepc->inputdev->id.bustype = BUS_HOST; - eeepc->inputdev->getkeycode = eeepc_getkeycode; - eeepc->inputdev->setkeycode = eeepc_setkeycode; - input_set_drvdata(eeepc->inputdev, eeepc); - - eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), - GFP_KERNEL); - for (key = eeepc_keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, eeepc->inputdev->evbit); - set_bit(key->keycode, eeepc->inputdev->keybit); - break; - } - } - result = input_register_device(eeepc->inputdev); - if (result) { - pr_info("Unable to register input device\n"); - input_free_device(eeepc->inputdev); - return result; - } + eeepc->inputdev = input; return 0; + + err_free_keymap: + sparse_keymap_free(input); + err_free_dev: + input_free_device(input); + return error; } static void eeepc_input_exit(struct eeepc_laptop *eeepc) @@ -1306,11 +1219,12 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) * event will be desired value (or else ignored) */ } - eeepc_input_notify(eeepc, event); + sparse_keymap_report_event(eeepc->inputdev, event, + 1, true); } } else { /* Everything else is a bona-fide keypress event */ - eeepc_input_notify(eeepc, event); + sparse_keymap_report_event(eeepc->inputdev, event, 1, true); } } @@ -1554,10 +1468,12 @@ static int __init eeepc_laptop_init(void) result = acpi_bus_register_driver(&eeepc_acpi_driver); if (result < 0) goto fail_acpi_driver; + if (!eeepc_device_present) { result = -ENODEV; goto fail_no_device; } + return 0; fail_no_device: -- cgit v1.2.3 From 322a1356be96bcc4b97e8e370f6468c821330077 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:40 +0100 Subject: eeepc-laptop: add hotplug_disable parameter Some new models need to disable wireless hotplug. For the moment, we don't know excactly what models need that, except 1005HA. Users will be able to use that param as a workaround. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 07d7978c558..a959abdea3a 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -50,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper"); MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); MODULE_LICENSE("GPL"); +static bool hotplug_disabled; + +module_param(hotplug_disabled, bool, 0644); +MODULE_PARM_DESC(hotplug_disabled, + "Disable hotplug for wireless device. " + "If your laptop need that, please report to " + "acpi4asus-user@lists.sourceforge.net."); + /* * Definitions for Asus EeePC */ @@ -1356,6 +1364,8 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; + eeepc->hotplug_disabled = hotplug_disabled; + eeepc_dmi_check(eeepc); result = eeepc_acpi_init(eeepc, device); -- cgit v1.2.3 From 4194e2f551a6308e6ab34ac88210bf54858aa7df Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 6 Jan 2010 22:07:41 +0100 Subject: eeepc-laptop: disable wireless hotplug for 1201N Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index a959abdea3a..e2be6bb33d9 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1277,7 +1277,7 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc) * hotplug code. In fact, current hotplug code seems to unplug another * device... */ - if (strcmp(model, "1005HA") == 0) { + if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { eeepc->hotplug_disabled = true; pr_info("wlan hotplug disabled\n"); } -- cgit v1.2.3 From 7a0b73a49ab56fb1e836675c00d6d0d2ba39a714 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Mon, 28 Dec 2009 10:39:23 -0800 Subject: ACPI: Fix section mismatch error for acpi_early_processor_set_pdc() Alex Chiang introduced acpi_early_processor_set_pdc() in commit: ACPI: processor: call _PDC early 78f1699659963fff97975df44db6d5dbe7218e55 But this results in a section mismatch: WARNING: drivers/acpi/acpi.o(.text+0xa9c1): Section mismatch in reference from the function acpi_early_processor_set_pdc() to the variable .cpuinit.data:processor_idle_dmi_table The function acpi_early_processor_set_pdc() references the variable __cpuinitdata processor_idle_dmi_table. This is often because acpi_early_processor_set_pdc lacks a __cpuinitdata annotation or the annotation of processor_idle_dmi_table is wrong. The only caller of acpi_early_processor_set_pdc() is acpi_bus_init() which is an "__init" function. So the correct fix here is to mark acpi_early_processor_set_pdc() "__init" too. Signed-off-by: Tony Luck Acked-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf3..7d4ee394d0b 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -151,7 +151,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void acpi_early_processor_set_pdc(void) +void __init acpi_early_processor_set_pdc(void) { /* * Check whether the system is DMI table. If yes, OSPM -- cgit v1.2.3 From 0b2c3688445ff02d3f1bfffc6983417b28f8c3da Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sat, 16 Jan 2010 20:43:12 +0100 Subject: i2c-core: Storage class should be before const qualifier The C99 specification states in section 6.11.5: The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature. Signed-off-by: Tobias Klauser Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 0ac2f90ab84..d610e995bbf 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -248,7 +248,7 @@ static const struct attribute_group *i2c_dev_attr_groups[] = { NULL }; -const static struct dev_pm_ops i2c_device_pm_ops = { +static const struct dev_pm_ops i2c_device_pm_ops = { .suspend = i2c_device_pm_suspend, .resume = i2c_device_pm_resume, }; -- cgit v1.2.3 From b6a3195070fe1c12d0bb1099ffe997d8abf9f602 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 16 Jan 2010 20:43:12 +0100 Subject: i2c: Test off by one in {piix4,vt596}_transaction() With `while (timeout++ < MAX_TIMEOUT)' timeout reaches MAX_TIMEOUT + 1 after the loop. This is probably unlikely to produce a problem. Signed-off-by: Roel Kluin Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-piix4.c | 4 ++-- drivers/i2c/busses/i2c-viapro.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 1e245e9cad3..e56e4b6823c 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -324,12 +324,12 @@ static int piix4_transaction(void) else msleep(1); - while ((timeout++ < MAX_TIMEOUT) && + while ((++timeout < MAX_TIMEOUT) && ((temp = inb_p(SMBHSTSTS)) & 0x01)) msleep(1); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout == MAX_TIMEOUT) { dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); result = -ETIMEDOUT; } diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index e4b1543015a..a84a909e123 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -165,10 +165,10 @@ static int vt596_transaction(u8 size) do { msleep(1); temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + } while ((temp & 0x01) && (++timeout < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { + if (timeout == MAX_TIMEOUT) { result = -ETIMEDOUT; dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); } -- cgit v1.2.3 From 7d53e79f9ec2842269754efbe34f53aa480d99e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: i2c-ali1563: Remove sparse warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the following sparse warnings (see "make C=1"): * drivers/i2c/busses/i2c-ali1563.c:91:3: warning: do-while statement is not a compound statement * drivers/i2c/busses/i2c-ali1563.c:161:3: warning: do-while statement is not a compound statement Signed-off-by: Márton Németh Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-ali1563.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index f70f46582c6..4687af40dd5 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -87,9 +87,9 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); timeout = ALI1563_MAX_TIMEOUT; - do + do { msleep(1); - while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); + } while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", @@ -157,9 +157,9 @@ static int ali1563_block_start(struct i2c_adapter * a) outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); timeout = ALI1563_MAX_TIMEOUT; - do + do { msleep(1); - while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); + } while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", -- cgit v1.2.3 From 22f8b2695eda496026623020811cae34590ee3d7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: i2c/pca: Don't use *_interruptible Unexpected signals can disturb the bus-handling and lock it up. Don't use interruptible in 'wait_event_*' and 'wake_*' as in commits dc1972d02747d2170fb1d78d114801f5ecb27506 (for cpm), 1ab082d7cbd0f34e39a5396cc6340c00bc5d66ef (for mpc), b7af349b175af45f9d87b3bf3f0a221e1831ed39 (for omap). Signed-off-by: Wolfram Sang Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pca-isa.c | 4 ++-- drivers/i2c/busses/i2c-pca-platform.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c index 0ed68e2ccd2..f7346a9bd95 100644 --- a/drivers/i2c/busses/i2c-pca-isa.c +++ b/drivers/i2c/busses/i2c-pca-isa.c @@ -75,7 +75,7 @@ static int pca_isa_waitforcompletion(void *pd) unsigned long timeout; if (irq > -1) { - ret = wait_event_interruptible_timeout(pca_wait, + ret = wait_event_timeout(pca_wait, pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI, pca_isa_ops.timeout); } else { @@ -96,7 +96,7 @@ static void pca_isa_resetchip(void *pd) } static irqreturn_t pca_handler(int this_irq, void *dev_id) { - wake_up_interruptible(&pca_wait); + wake_up(&pca_wait); return IRQ_HANDLED; } diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index c4df9d411cd..5b2213df5ed 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -84,7 +84,7 @@ static int i2c_pca_pf_waitforcompletion(void *pd) unsigned long timeout; if (i2c->irq) { - ret = wait_event_interruptible_timeout(i2c->wait, + ret = wait_event_timeout(i2c->wait, i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI, i2c->adap.timeout); } else { @@ -122,7 +122,7 @@ static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id) if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) return IRQ_NONE; - wake_up_interruptible(&i2c->wait); + wake_up(&i2c->wait); return IRQ_HANDLED; } -- cgit v1.2.3 From c556752109794a5ff199b80a1673336b4df8433a Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Sat, 16 Jan 2010 20:43:13 +0100 Subject: i2c: Do not use device name after device_unregister MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev_dbg outputs dev_name, which is released with device_unregister. This bug resulted in output like this: i2c Xy2�0: adapter [SMBus I801 adapter at 1880] unregistered The right output would be: i2c i2c-0: adapter [SMBus I801 adapter at 1880] unregistered Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index d610e995bbf..10be7b5fbe9 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -843,6 +843,9 @@ int i2c_del_adapter(struct i2c_adapter *adap) adap->dev.parent); #endif + /* device name is gone after device_unregister */ + dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); + /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev); @@ -855,8 +858,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) idr_remove(&i2c_adapter_idr, adap->nr); mutex_unlock(&core_lock); - dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); - /* Clear the device structure in case this adapter is ever going to be added again */ memset(&adap->dev, 0, sizeof(adap->dev)); -- cgit v1.2.3 From 0b94190e1e60f96962b82d35729d7d44cf298ef8 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Fri, 15 Jan 2010 17:01:03 -0800 Subject: viafb: fix LCD hardware cursor regression Although I'd consider this a hardware bug, as there is hardware out that for whatever reason does not support hardware cursors on LCD output we have to care about it in the driver. This fixes a regression (invisible cursor) introduced by: viafb: cleanup viafb_cursor Signed-off-by: Florian Tobias Schandinat Reported-by: Julian Wollrath Tested-by: Julian Wollrath Cc: Scott Fang Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/viafbdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index d8df17a7d5f..a0004c17af6 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -872,7 +872,9 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo) return -ENODEV; - if (chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) + /* LCD ouput does not support hw cursors (at least on VN896) */ + if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) || + viafb_LCD_ON) return -ENODEV; viafb_show_hw_cursor(info, HW_Cursor_OFF); -- cgit v1.2.3 From 8a3a95c32f612068be8dae74fa5fc4cf2db1592e Mon Sep 17 00:00:00 2001 From: Erik-Jan Post Date: Fri, 15 Jan 2010 17:01:05 -0800 Subject: viafb: do modesetting after updating variables Reorder viafb_set_par to allow using the updated variables in viafb_setmode. This fixes a regression that prevented proper runtime mode changes. Signed-off-by: Erik-Jan Post Signed-off-by: Florian Tobias Schandinat Cc: Scott Fang Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/viafbdev.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index a0004c17af6..3028e7ddc3b 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -177,16 +177,15 @@ static int viafb_set_par(struct fb_info *info) } if (vmode_index != VIA_RES_INVALID) { - viafb_setmode(vmode_index, info->var.xres, info->var.yres, - info->var.bits_per_pixel, vmode_index1, - viafb_second_xres, viafb_second_yres, viafb_bpp1); - viafb_update_fix(info); viafb_bpp = info->var.bits_per_pixel; if (info->var.accel_flags & FB_ACCELF_TEXT) info->flags &= ~FBINFO_HWACCEL_DISABLED; else info->flags |= FBINFO_HWACCEL_DISABLED; + viafb_setmode(vmode_index, info->var.xres, info->var.yres, + info->var.bits_per_pixel, vmode_index1, + viafb_second_xres, viafb_second_yres, viafb_bpp1); } return 0; -- cgit v1.2.3 From 97922b5462fa543484831d42ab0fe4562b9373fc Mon Sep 17 00:00:00 2001 From: Erik-Jan Post Date: Fri, 15 Jan 2010 17:01:06 -0800 Subject: viafb: fix acceleration for some chips Fix a regression in hardware acceleration which made the accelerated framebuffer unusable on some chips. These need extra initialization and an extra flag which is no longer needed/available on current chips. Signed-off-by: Erik-Jan Post Signed-off-by: Florian Tobias Schandinat Cc: Scott Fang Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/accel.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 9d4f3a49ba4..d5077dfa9e0 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -137,7 +137,7 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, tmp, dst_pitch); return -EINVAL; } - tmp = (tmp >> 3) | (dst_pitch << (16 - 3)); + tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3)); writel(tmp, engine + 0x38); if (op == VIA_BITBLT_FILL) @@ -352,6 +352,9 @@ int viafb_init_engine(struct fb_info *info) viapar->shared->vq_vram_addr = viapar->fbmem_free; viapar->fbmem_used += VQ_SIZE; + /* Init 2D engine reg to reset 2D engine */ + writel(0x0, engine + VIA_REG_KEYCONTROL); + /* Init AGP and VQ regs */ switch (chip_name) { case UNICHROME_K8M890: -- cgit v1.2.3 From 3018aa4b1a46946dfd0ee73a533038f24e390539 Mon Sep 17 00:00:00 2001 From: Ping Date: Fri, 15 Jan 2010 17:01:07 -0800 Subject: serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device This is a new two finger touch Fujitsu Wacom Tablet PC. Signed-off-by: Ping Cheng Cc: Alan Cox Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/8250_pnp.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index 36ede02ceac..b5496a19d96 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -354,6 +354,8 @@ static const struct pnp_device_id pnp_dev_table[] = { { "FUJ02E5", 0 }, /* Fujitsu P-series tablet PC device */ { "FUJ02E6", 0 }, + /* Fujitsu Wacom 2FGT Tablet PC device */ + { "FUJ02E7", 0 }, /* * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in * disguise) -- cgit v1.2.3 From 118f3e1afd5534c15f9701f33514186cfc841a27 Mon Sep 17 00:00:00 2001 From: Tamas Vincze Date: Fri, 15 Jan 2010 17:01:10 -0800 Subject: edac: i5000_edac critical fix panic out of bounds EDAC MC0: INTERNAL ERROR: channel-b out of range (4 >= 4) Kernel panic - not syncing: EDAC MC0: Uncorrected Error (XEN) Domain 0 crashed: 'noreboot' set - not rebooting. This happens because FERR_NF_FBD bit 28 is not updated on i5000. Due to that, both bits 28 and 29 may be equal to one, returning channel = 3. As this value is invalid, EDAC core generates the panic. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=14568 Signed-off-by: Tamas Vincze Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Doug Thompson Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i5000_edac.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index 77a9579d716..adc10a2ac5f 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -577,7 +577,13 @@ static void i5000_process_nonfatal_error_info(struct mem_ctl_info *mci, debugf0("\tUncorrected bits= 0x%x\n", ue_errors); branch = EXTRACT_FBDCHAN_INDX(info->ferr_nf_fbd); - channel = branch; + + /* + * According with i5000 datasheet, bit 28 has no significance + * for errors M4Err-M12Err and M17Err-M21Err, on FERR_NF_FBD + */ + channel = branch & 2; + bank = NREC_BANK(info->nrecmema); rank = NREC_RANK(info->nrecmema); rdwr = NREC_RDWR(info->nrecmema); -- cgit v1.2.3 From d817cd525589765aa5f6798734e422c867685a58 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney Date: Fri, 15 Jan 2010 17:01:26 -0800 Subject: virtio: fix section mismatch warnings Fix fixes the following warnings by renaming the driver structures to be suffixed with _driver. WARNING: drivers/virtio/virtio_balloon.o(.data+0x88): Section mismatch in reference from the variable virtio_balloon to the function .devexit.text:virtballoon_remove() WARNING: drivers/char/hw_random/virtio-rng.o(.data+0x88): Section mismatch in reference from the variable virtio_rng to the function .devexit.text:virtrng_remove() Signed-off-by: Jeff Mahoney Acked-by: Rusty Russell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/hw_random/virtio-rng.c | 6 +++--- drivers/virtio/virtio_balloon.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index bdaef8e9402..64fe0a793ef 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -114,7 +114,7 @@ static struct virtio_device_id id_table[] = { { 0 }, }; -static struct virtio_driver virtio_rng = { +static struct virtio_driver virtio_rng_driver = { .driver.name = KBUILD_MODNAME, .driver.owner = THIS_MODULE, .id_table = id_table, @@ -124,12 +124,12 @@ static struct virtio_driver virtio_rng = { static int __init init(void) { - return register_virtio_driver(&virtio_rng); + return register_virtio_driver(&virtio_rng_driver); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_rng); + unregister_virtio_driver(&virtio_rng_driver); } module_init(init); module_exit(fini); diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 9dd58804288..505be88c82a 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -266,7 +266,7 @@ static void __devexit virtballoon_remove(struct virtio_device *vdev) static unsigned int features[] = { VIRTIO_BALLOON_F_MUST_TELL_HOST }; -static struct virtio_driver virtio_balloon = { +static struct virtio_driver virtio_balloon_driver = { .feature_table = features, .feature_table_size = ARRAY_SIZE(features), .driver.name = KBUILD_MODNAME, @@ -279,12 +279,12 @@ static struct virtio_driver virtio_balloon = { static int __init init(void) { - return register_virtio_driver(&virtio_balloon); + return register_virtio_driver(&virtio_balloon_driver); } static void __exit fini(void) { - unregister_virtio_driver(&virtio_balloon); + unregister_virtio_driver(&virtio_balloon_driver); } module_init(init); module_exit(fini); -- cgit v1.2.3 From ba168fc37dea145deeb8fa9e7e71c748d2e00d74 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 15 Jan 2010 17:01:31 -0800 Subject: memory-hotplug: add 0x prefix to HEX block_size_bytes Signed-off-by: Wu Fengguang Cc: Andi Kleen Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index d7d77d4a402..bd025059711 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -311,7 +311,7 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); static ssize_t print_block_size(struct class *class, char *buf) { - return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); + return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); -- cgit v1.2.3 From 8ff410daa009c4b44be445ded5b0cec00abc0426 Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 15 Jan 2010 17:01:32 -0800 Subject: sysdev: fix prototype for memory_sysdev_class show/store functions The function prototype mismatches in call stack: [] print_block_size+0x58/0x60 [] sysdev_class_show+0x1f/0x30 [] sysfs_read_file+0xcb/0x1f0 [] vfs_read+0xc8/0x180 Due to prototype mismatch, print_block_size() will sprintf() into *attribute instead of *buf, hence user space will read the initial zeros from *buf: $ hexdump /sys/devices/system/memory/block_size_bytes 0000000 0000 0000 0000 0000 0000008 After patch: cat /sys/devices/system/memory/block_size_bytes 0x8000000 This complements commits c29af9636 and 4a0b2b4dbe. Signed-off-by: Wu Fengguang Cc: Andi Kleen Cc: Greg Kroah-Hartman Cc: "Zheng, Shaohui" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/memory.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index bd025059711..ae6b6c43cff 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -309,17 +309,19 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); * Block size attribute stuff */ static ssize_t -print_block_size(struct class *class, char *buf) +print_block_size(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + char *buf) { return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } -static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_block_size_bytes.attr); + &attr_block_size_bytes.attr); } /* @@ -330,7 +332,9 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct class *class, const char *buf, size_t count) +memory_probe_store(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + const char *buf, size_t count) { u64 phys_addr; int nid; @@ -346,12 +350,12 @@ memory_probe_store(struct class *class, const char *buf, size_t count) return count; } -static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); +static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_probe.attr); + &attr_probe.attr); } #else static inline int memory_probe_init(void) @@ -367,7 +371,9 @@ static inline int memory_probe_init(void) /* Soft offline a page */ static ssize_t -store_soft_offline_page(struct class *class, const char *buf, size_t count) +store_soft_offline_page(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + const char *buf, size_t count) { int ret; u64 pfn; @@ -384,7 +390,9 @@ store_soft_offline_page(struct class *class, const char *buf, size_t count) /* Forcibly offline a page, including killing processes. */ static ssize_t -store_hard_offline_page(struct class *class, const char *buf, size_t count) +store_hard_offline_page(struct sysdev_class *class, + struct sysdev_class_attribute *class_attr, + const char *buf, size_t count) { int ret; u64 pfn; @@ -397,18 +405,18 @@ store_hard_offline_page(struct class *class, const char *buf, size_t count) return ret ? ret : count; } -static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); -static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); +static SYSDEV_CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); +static SYSDEV_CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); static __init int memory_fail_init(void) { int err; err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_soft_offline_page.attr); + &attr_soft_offline_page.attr); if (!err) err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &class_attr_hard_offline_page.attr); + &attr_hard_offline_page.attr); return err; } #else -- cgit v1.2.3 From eb29a5cc0b601c458bae9df2f6c3696d75c2d383 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 15 Jan 2010 17:01:40 -0800 Subject: revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC Framebuffer" Fix divide by zero and broken output. Commit 600ce1a0fa ("fix clock setting for Samsung SoC Framebuffer") introduced a mandatory refresh parameter to the platform data for the S3C framebuffer but did not introduce any validation code, causing existing platforms (none of which have refresh set) to divide by zero whenever the framebuffer is configured, generating warnings and unusable output. Ben Dooks noted several problems with the patch: - The platform data supplies the pixclk directly and should already have taken care of the refresh rate. - The addition of a window ID parameter doesn't help since only the root framebuffer can control the pixclk. - pixclk is specified in picoseconds (rather than Hz) as the patch assumed. and suggests reverting the commit so do that. Without fixing this no mainline user of the driver will produce output. [akpm@linux-foundation.org: don't revert the correct bit] Signed-off-by: Mark Brown Cc: InKi Dae Cc: Kyungmin Park Cc: Krzysztof Helt Cc: Marek Szyprowski Cc: Ben Dooks Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/s3c-fb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index adf9632c6b1..53cb722c45a 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c @@ -211,21 +211,23 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /** * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. - * @id: window id. * @sfb: The hardware state. * @pixclock: The pixel clock wanted, in picoseconds. * * Given the specified pixel clock, work out the necessary divider to get * close to the output frequency. */ -static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk) +static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) { - struct s3c_fb_pd_win *win = sfb->pdata->win[id]; unsigned long clk = clk_get_rate(sfb->bus_clk); + unsigned long long tmp; unsigned int result; - pixclk *= win->win_mode.refresh; - result = clk / pixclk; + tmp = (unsigned long long)clk; + tmp *= pixclk; + + do_div(tmp, 1000000000UL); + result = (unsigned int)tmp / 1000; dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", pixclk, clk, result, clk / result); @@ -301,7 +303,7 @@ static int s3c_fb_set_par(struct fb_info *info) /* use window 0 as the basis for the lcd output timings */ if (win_no == 0) { - clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock); + clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); data = sfb->pdata->vidcon0; data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); -- cgit v1.2.3 From c14973f93027500301fc40333e16ae49e58923a7 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 10 Jan 2010 00:15:44 -0800 Subject: sony-laptop - fix using of uninitialized variable CC [M] drivers/platform/x86/sony-laptop.o drivers/platform/x86/sony-laptop.c: In function 'sony_nc_rfkill_setup': drivers/platform/x86/sony-laptop.c:1162: warning: 'i' may be used uninitialized in this function Signed-off-by: Dmitry Torokhov Acked-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6..3f71a605a49 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) /* the buffer is filled with magic numbers describing the devices * available, 0xff terminates the enumeration */ - while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && - i < device_enum->buffer.length) { - i++; + for (i = 0; i < device_enum->buffer.length; i++) { + + dev_code = *(device_enum->buffer.pointer + i); + if (dev_code == 0xff) + break; + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) -- cgit v1.2.3 From c97adf9e7bebf17a86b95e2131bf9ba76c4857c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sun, 10 Jan 2010 17:15:36 +0100 Subject: acpi: make ACPI device id constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ids field of the struct acpi_driver is constant in so it is worth to make the initialization data also constant. The semantic match that finds this kind of pattern is as follows: (http://coccinelle.lip6.fr/) // @r@ disable decl_init,const_decl_init; identifier I1, I2, x; @@ struct I1 { ... const struct I2 *x; ... }; @s@ identifier r.I1, y; identifier r.x, E; @@ struct I1 y = { .x = E, }; @c@ identifier r.I2; identifier s.E; @@ const struct I2 E[] = ... ; @depends on !c@ identifier r.I2; identifier s.E; @@ + const struct I2 E[] = ...; // Signed-off-by: Márton Németh Cc: Julia Lawall Cc: cocci@diku.dk Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 2 +- drivers/acpi/pci_root.c | 2 +- drivers/acpi/power.c | 2 +- drivers/acpi/power_meter.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 394ae89409c..04b0f007c9b 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link"); static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); -static struct acpi_device_id link_device_ids[] = { +static const struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 101cce3681d..64f55b6db73 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); -static struct acpi_device_id root_device_ids[] = { +static const struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 22b29791651..0f30c3c1eea 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); static int acpi_power_open_fs(struct inode *inode, struct file *file); -static struct acpi_device_id power_device_ids[] = { +static const struct acpi_device_id power_device_ids[] = { {ACPI_POWER_HID, 0}, {"", 0}, }; diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index 2ef7030a0c2..ca75c36f754 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -64,7 +64,7 @@ static int can_cap_in_hardware(void) return force_cap_on || cap_in_hardware; } -static struct acpi_device_id power_meter_ids[] = { +static const struct acpi_device_id power_meter_ids[] = { {"ACPI000D", 0}, {"", 0}, }; -- cgit v1.2.3 From c19bdb6126a5e1f43b4a4fc3c4b09c926667e5ef Mon Sep 17 00:00:00 2001 From: Rakib Mullick Date: Sun, 3 Jan 2010 19:27:56 +0600 Subject: ACPI: Fix unused variable warning in sbs.c When CONFIG_ACPI_SYSFS_POWER=n and CONFIG_ACPI_PROCFS_POWER=n, then we're warned by the following warning: drivers/acpi/sbs.c: In function `acpi_battery_remove': drivers/acpi/sbs.c:825: warning: unused variable `battery' Signed-off-by: Rakib Mullick Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 52b9db8afc2..b16ddbf23a9 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { +#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) struct acpi_battery *battery = &sbs->battery[id]; +#endif + #ifdef CONFIG_ACPI_SYSFS_POWER if (battery->bat.dev) { if (battery->have_sysfs_alarm) -- cgit v1.2.3 From 8c32aa5945cb05bb2ff8a91485d4477fbe55cf00 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Mon, 14 Dec 2009 14:57:49 -0300 Subject: V4L/DVB (13816): gspca - main: Set the current frame pointer when first qbuf. When not set, some images could be lost. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e930a67d526..bd6214d4ab3 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1815,6 +1815,8 @@ static int vidioc_qbuf(struct file *file, void *priv, /* put the buffer in the 'queued' queue */ i = gspca_dev->fr_q; gspca_dev->fr_queue[i] = index; + if (gspca_dev->fr_i == i) + gspca_dev->cur_frame = frame; gspca_dev->fr_q = (i + 1) % gspca_dev->nframes; PDEBUG(D_FRAM, "qbuf q:%d i:%d o:%d", gspca_dev->fr_q, -- cgit v1.2.3 From 1faea56087dfaf84019557f2c9ad18bd67c6012a Mon Sep 17 00:00:00 2001 From: Nemeth Marton Date: Tue, 15 Dec 2009 19:28:35 -0300 Subject: V4L/DVB (13820): lgdt3305: make one-bit bitfields unsigned Make one-bit bitfields unsigned which will remove the following sparse warning messages (see "make C=1"): * lgdt3305.h:57:21: error: dubious one-bit signed bitfield * lgdt3305.h:60:26: error: dubious one-bit signed bitfield * lgdt3305.h:63:19: error: dubious one-bit signed bitfield Signed-off-by: Nemeth Marton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/lgdt3305.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h index 4fa6e52d1fe..9cb11c9cae5 100644 --- a/drivers/media/dvb/frontends/lgdt3305.h +++ b/drivers/media/dvb/frontends/lgdt3305.h @@ -54,13 +54,13 @@ struct lgdt3305_config { u16 usref_qam256; /* default: 0x2a80 */ /* disable i2c repeater - 0:repeater enabled 1:repeater disabled */ - int deny_i2c_rptr:1; + unsigned int deny_i2c_rptr:1; /* spectral inversion - 0:disabled 1:enabled */ - int spectral_inversion:1; + unsigned int spectral_inversion:1; /* use RF AGC loop - 0:disabled 1:enabled */ - int rf_agc_loop:1; + unsigned int rf_agc_loop:1; enum lgdt3305_mpeg_mode mpeg_mode; enum lgdt3305_tp_clock_edge tpclk_edge; -- cgit v1.2.3 From 385097e08b9c24655626ed760bc67eb7e50115a0 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 9 Dec 2009 22:31:21 -0300 Subject: V4L/DVB (13826): uvcvideo: Fix controls blacklisting The control blacklisting code erroneously used usb_match_id() by passing a pointer to a usb_device_id structure instead of an array of such structures. Replace the usb_match_id() call by usb_match_id_one(). Thanks to Paulo Assis for diagnosing the bug and providing an initial fix. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 0469d7a876a..ec8ef8c5560 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c @@ -1393,7 +1393,7 @@ uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity) size = entity->processing.bControlSize; for (i = 0; i < ARRAY_SIZE(blacklist); ++i) { - if (!usb_match_id(dev->intf, &blacklist[i].id)) + if (!usb_match_one_id(dev->intf, &blacklist[i].id)) continue; if (blacklist[i].index >= 8 * size || -- cgit v1.2.3 From 2c4d9de8ab1434336248bbc01ee8e64d7e6b8a4f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 10 Dec 2009 21:19:31 -0300 Subject: V4L/DVB (13829): uvcvideo: Fix alternate setting selection in isochronous mode Unlike assumed by the driver, alternate settings are not sorted by endpoint max packet size. Iterate over all alternate settings to find the one with the smallest compatible max packet size. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 9a9802830d4..e8cc0a9ddad 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -924,10 +924,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream, static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) { struct usb_interface *intf = stream->intf; - struct usb_host_interface *alts; - struct usb_host_endpoint *ep = NULL; - int intfnum = stream->intfnum; - unsigned int bandwidth, psize, i; + struct usb_host_endpoint *ep; + unsigned int i; int ret; stream->last_fid = -1; @@ -936,6 +934,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) stream->bulk.payload_size = 0; if (intf->num_altsetting > 1) { + struct usb_host_endpoint *best_ep = NULL; + unsigned int best_psize = 3 * 1024; + unsigned int bandwidth; + unsigned int uninitialized_var(altsetting); + int intfnum = stream->intfnum; + /* Isochronous endpoint, select the alternate setting. */ bandwidth = stream->ctrl.dwMaxPayloadTransferSize; @@ -949,6 +953,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) } for (i = 0; i < intf->num_altsetting; ++i) { + struct usb_host_interface *alts; + unsigned int psize; + alts = &intf->altsetting[i]; ep = uvc_find_endpoint(alts, stream->header.bEndpointAddress); @@ -958,21 +965,27 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) /* Check if the bandwidth is high enough. */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - if (psize >= bandwidth) - break; + if (psize >= bandwidth && psize <= best_psize) { + altsetting = i; + best_psize = psize; + best_ep = ep; + } } - if (i >= intf->num_altsetting) { + if (best_ep == NULL) { uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " "for requested bandwidth.\n"); return -EIO; } - ret = usb_set_interface(stream->dev->udev, intfnum, i); + uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u " + "(%u B/frame bandwidth).\n", altsetting, best_psize); + + ret = usb_set_interface(stream->dev->udev, intfnum, altsetting); if (ret < 0) return ret; - ret = uvc_init_video_isoc(stream, ep, gfp_flags); + ret = uvc_init_video_isoc(stream, best_ep, gfp_flags); } else { /* Bulk endpoint, proceed to URB initialization. */ ep = uvc_find_endpoint(&intf->altsetting[0], -- cgit v1.2.3 From d7c0d43997cf716617d724554d19b3b8dd465833 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 16 Dec 2009 21:20:45 -0300 Subject: V4L/DVB (13831): uvcvideo: Fix oops caused by a race condition in buffer dequeuing Buffers were marked as done before being removed from the IRQ queue. If a userspace application dequeued and requeued the buffer fast enough during that time window, the buffer could end up being deleted twice, generating an oops in interrupt context. Add a new state, UVC_BUF_STATE_READY, to mark buffers as ready for reuse but not yet removed from the queue, and transition to UVC_BUF_STATE_DONE only when the buffer is removed from the queue. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_queue.c | 13 +++++++++---- drivers/media/video/uvc/uvc_video.c | 14 ++++++-------- drivers/media/video/uvc/uvcvideo.h | 5 +++-- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f854698c406..ea11839cba4 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -59,9 +59,9 @@ * returns immediately. * * When the buffer is full, the completion handler removes it from the irq - * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. + * queue, marks it as done (UVC_BUF_STATE_DONE) and wakes its wait queue. * At that point, any process waiting on the buffer will be woken up. If a - * process tries to dequeue a buffer after it has been marked ready, the + * process tries to dequeue a buffer after it has been marked done, the * dequeing will succeed immediately. * * 2. Buffers are queued, user is waiting on a buffer and the device gets @@ -201,6 +201,7 @@ static void __uvc_query_buffer(struct uvc_buffer *buf, break; case UVC_BUF_STATE_QUEUED: case UVC_BUF_STATE_ACTIVE: + case UVC_BUF_STATE_READY: v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; break; case UVC_BUF_STATE_IDLE: @@ -295,13 +296,15 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) { if (nonblocking) { return (buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE) + buf->state != UVC_BUF_STATE_ACTIVE && + buf->state != UVC_BUF_STATE_READY) ? 0 : -EAGAIN; } return wait_event_interruptible(buf->wait, buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE); + buf->state != UVC_BUF_STATE_ACTIVE && + buf->state != UVC_BUF_STATE_READY); } /* @@ -348,6 +351,7 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, case UVC_BUF_STATE_IDLE: case UVC_BUF_STATE_QUEUED: case UVC_BUF_STATE_ACTIVE: + case UVC_BUF_STATE_READY: default: uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " "(driver bug?).\n", buf->state); @@ -489,6 +493,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, spin_lock_irqsave(&queue->irqlock, flags); list_del(&buf->queue); + buf->state = UVC_BUF_STATE_DONE; if (!list_empty(&queue->irqqueue)) nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index e8cc0a9ddad..7dcf534a0cf 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -441,7 +441,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, if (fid != stream->last_fid && buf->buf.bytesused != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " "toggled).\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; return -EAGAIN; } @@ -470,7 +470,7 @@ static void uvc_video_decode_data(struct uvc_streaming *stream, /* Complete the current frame if the buffer size was exceeded. */ if (len > maxlen) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; } } @@ -482,7 +482,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream, uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); if (data[0] == len) uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) stream->last_fid ^= UVC_STREAM_FID; } @@ -568,8 +568,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, uvc_video_decode_end(stream, buf, mem, urb->iso_frame_desc[i].actual_length); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) + if (buf->state == UVC_BUF_STATE_READY) buf = uvc_queue_next_buffer(&stream->queue, buf); } } @@ -627,8 +626,7 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream, if (!stream->bulk.skip_payload && buf != NULL) { uvc_video_decode_end(stream, buf, stream->bulk.header, stream->bulk.payload_size); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) + if (buf->state == UVC_BUF_STATE_READY) buf = uvc_queue_next_buffer(&stream->queue, buf); } @@ -669,7 +667,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, stream->bulk.payload_size == stream->bulk.max_payload_size) { if (buf->buf.bytesused == stream->queue.buf_used) { stream->queue.buf_used = 0; - buf->state = UVC_BUF_STATE_DONE; + buf->state = UVC_BUF_STATE_READY; uvc_queue_next_buffer(&stream->queue, buf); stream->last_fid ^= UVC_STREAM_FID; } diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 7ec9a04ced5..2337585001e 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -365,8 +365,9 @@ enum uvc_buffer_state { UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_QUEUED = 1, UVC_BUF_STATE_ACTIVE = 2, - UVC_BUF_STATE_DONE = 3, - UVC_BUF_STATE_ERROR = 4, + UVC_BUF_STATE_READY = 3, + UVC_BUF_STATE_DONE = 4, + UVC_BUF_STATE_ERROR = 5, }; struct uvc_buffer { -- cgit v1.2.3 From 9afc8022b4e7e4e8c572b2b997846756afb5d909 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Dec 2009 07:47:44 -0300 Subject: V4L/DVB (13834): dib8000: fix compilation if !DVB_DIB8000 As reported by Randy Dunlap : > drivers/media/dvb/frontends/dib8000.h:104: error: expected expression before '}' token > drivers/media/dvb/frontends/dib8000.h:104: warning: left-hand operand of comma expression has no effect > > return CT_SHUTDOWN, > > s/,/;/ and fix indentation. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dib8000.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index d99619ae983..b1ee2079963 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h @@ -100,7 +100,7 @@ static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_ static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return CT_SHUTDOWN, + return CT_SHUTDOWN; } static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) { -- cgit v1.2.3 From bc41797a56e7995dd5f5502dd737b1e53c8e0410 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 10 Dec 2009 13:21:59 -0300 Subject: V4L/DVB (13622): gspca - ov534: Fix a compilation warning. This warning prevented the sharpness setting to work with the ov965x sensor. Reported-by: Andrew Morton Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/ov534.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c index 4dbb882c83d..0a6b8f07a69 100644 --- a/drivers/media/video/gspca/ov534.c +++ b/drivers/media/video/gspca/ov534.c @@ -1533,7 +1533,7 @@ static void setexposure_96(struct gspca_dev *gspca_dev) static void setsharpness_96(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - u8 val; + s8 val; val = sd->sharpness; if (val < 0) { /* auto */ -- cgit v1.2.3 From 882ead325b167cdab89f58f871dabf9de5ac87a4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 29 Dec 2009 10:37:38 -0300 Subject: V4L/DVB (13858): ir-keytable: use the right header We don't need linux/usb/input.h but, instead, linux/input.h Signed-off-by: Mauro Carvalho Chehab --- drivers/media/IR/ir-keytable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index bff7a535603..b521ed9d6e2 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -13,7 +13,7 @@ */ -#include +#include #include #define IR_TAB_MIN_SIZE 32 -- cgit v1.2.3 From c60503c1db76bd46577cc7ff4fafa033b675e0e5 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 18 Dec 2009 12:22:43 -0300 Subject: V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned. Signed-off-by: Roel Kluin Signed-off-by: Jean-Francois Moine CC: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sn9c20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 4cff8035614..0ca1c06652b 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c @@ -2319,7 +2319,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) } } if (avg_lum > MAX_AVG_LUM) { - if (sd->gain - 1 >= 0) { + if (sd->gain >= 1) { sd->gain--; set_gain(gspca_dev); } -- cgit v1.2.3 From 9501843496aaf85fe1767b534c4720622c4425c4 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sat, 26 Dec 2009 08:41:17 -0300 Subject: V4L/DVB (13875): gspca - vc032x: Fix a possible crash with the vc0321 bridge. The frame pointer returned by get_i_frame may be NULL when the application is too slow. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/vc032x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index c090efcd804..71921c87842 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -3009,6 +3009,10 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, int l; frame = gspca_get_i_frame(gspca_dev); + if (frame == NULL) { + gspca_dev->last_packet_type = DISCARD_PACKET; + return; + } l = frame->data_end - frame->data; if (len > frame->v4l2_buf.length - l) len = frame->v4l2_buf.length - l; -- cgit v1.2.3 From 5cc60d61432f30b2d0777a15d050f6c0613887f5 Mon Sep 17 00:00:00 2001 From: Erik Andren Date: Wed, 11 Nov 2009 07:45:37 -0300 Subject: V4L/DVB (13880): gspca - m5602-s5k4aa: Add vflip quirk for the Amilo Xi 2428 Add a vflip quirk for the Fujitsu-Siemens Amilo Xi 2428. Thanks to Myroslav Zapukhlyak for reporting. Signed-off-by: Erik Andren Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index aa2f3c7e2cb..1b536f7d30c 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -47,6 +47,12 @@ static DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528") } + }, { + .ident = "Fujitsu-Siemens Amilo Xi 2428", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428") + } }, { .ident = "Fujitsu-Siemens Amilo Xi 2528", .matches = { -- cgit v1.2.3 From bbe8c8363da7251b41ee9cdb70059f04fd1bee9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Andr=C3=A9n?= Date: Sat, 26 Dec 2009 18:57:21 -0300 Subject: V4L/DVB (13882): gspca - stv06xx-vv6410: Ensure register STV_SCAN_RATE is zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Quickcam Web camera would not produce an image if you removed and inserted the module multiple times without physically power cycling the camera first. By writing zero to bridge register STV_SCAN_RATE (0x1443) the camera works as intended, regardless of the number of module insertions. Signed-off-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h index 487d4055534..96c61926d37 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h @@ -228,6 +228,7 @@ static const struct stv_init stv_bridge_init[] = { /* This reg is written twice. Some kind of reset? */ {NULL, 0x1620, 0x80}, {NULL, 0x1620, 0x00}, + {NULL, 0x1443, 0x00}, {NULL, 0x1423, 0x04}, {x1500, 0x1500, ARRAY_SIZE(x1500)}, {x1536, 0x1536, ARRAY_SIZE(x1536)}, -- cgit v1.2.3 From 19f8a6c37eead7e93660813c8873ab3e387ccb63 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 31 Dec 2009 04:32:29 -0300 Subject: V4L/DVB (13887): tda8290: add autodetection support for TDA8295c2 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda8290.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index c190b0dedee..19010f3d450 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -672,16 +672,19 @@ static int tda8290_probe(struct tuner_i2c_props *i2c_props) static int tda8295_probe(struct tuner_i2c_props *i2c_props) { #define TDA8295_ID 0x8a +#define TDA8295C2_ID 0x8b unsigned char tda8295_id[] = { 0x2f, 0x00 }; /* detect tda8295 */ tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1); tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1); - if (tda8295_id[1] == TDA8295_ID) { + if ((tda8295_id[1] & 0xfe) == TDA8295_ID) { if (debug) - printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n", - __func__, i2c_adapter_id(i2c_props->adap), + printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n", + __func__, (tda8295_id[1] == TDA8295_ID) ? + "tda8295c1" : "tda8295c2", + i2c_adapter_id(i2c_props->adap), i2c_props->addr); return 0; } -- cgit v1.2.3 From 07d1c69b2dcfdd1b21e36af0ff8b9506234908ee Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Sun, 10 Jan 2010 04:32:11 -0300 Subject: V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges. A previous code optimization inverted bridge registers and values, doing a regression in kernel 2.6.32. Signed-off-by: Jean-Francois Moine CC: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/sunplus.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index 716df6b15fc..306b7d75b4a 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c @@ -709,7 +709,7 @@ static void spca504B_SetSizeType(struct gspca_dev *gspca_dev) spca504B_PollingDataReady(gspca_dev); /* Init the cam width height with some values get on init ? */ - reg_w_riv(gspca_dev, 0x31, 0, 0x04); + reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; @@ -807,14 +807,14 @@ static void init_ctl_reg(struct gspca_dev *gspca_dev) default: /* case BRIDGE_SPCA533: */ /* case BRIDGE_SPCA504B: */ - reg_w_riv(gspca_dev, 0, 0x00, 0x21ad); /* hue */ - reg_w_riv(gspca_dev, 0, 0x01, 0x21ac); /* sat/hue */ - reg_w_riv(gspca_dev, 0, 0x00, 0x21a3); /* gamma */ + reg_w_riv(gspca_dev, 0, 0x21ad, 0x00); /* hue */ + reg_w_riv(gspca_dev, 0, 0x21ac, 0x01); /* sat/hue */ + reg_w_riv(gspca_dev, 0, 0x21a3, 0x00); /* gamma */ break; case BRIDGE_SPCA536: - reg_w_riv(gspca_dev, 0, 0x40, 0x20f5); - reg_w_riv(gspca_dev, 0, 0x01, 0x20f4); - reg_w_riv(gspca_dev, 0, 0x00, 0x2089); + reg_w_riv(gspca_dev, 0, 0x20f5, 0x40); + reg_w_riv(gspca_dev, 0, 0x20f4, 0x01); + reg_w_riv(gspca_dev, 0, 0x2089, 0x00); break; } if (pollreg) @@ -887,11 +887,11 @@ static int sd_init(struct gspca_dev *gspca_dev) switch (sd->bridge) { case BRIDGE_SPCA504B: reg_w_riv(gspca_dev, 0x1d, 0x00, 0); - reg_w_riv(gspca_dev, 0, 0x01, 0x2306); - reg_w_riv(gspca_dev, 0, 0x00, 0x0d04); - reg_w_riv(gspca_dev, 0, 0x00, 0x2000); - reg_w_riv(gspca_dev, 0, 0x13, 0x2301); - reg_w_riv(gspca_dev, 0, 0x00, 0x2306); + reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01); + reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00); + reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00); + reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13); + reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00); /* fall thru */ case BRIDGE_SPCA533: spca504B_PollingDataReady(gspca_dev); @@ -1000,7 +1000,7 @@ static int sd_start(struct gspca_dev *gspca_dev) spca504B_WaitCmdStatus(gspca_dev); break; default: - reg_w_riv(gspca_dev, 0x31, 0, 0x04); + reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00); spca504B_WaitCmdStatus(gspca_dev); spca504B_PollingDataReady(gspca_dev); break; -- cgit v1.2.3 From 3f76cf8c8ed10da1ce50f821366d0dc590397069 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 10 Jan 2010 18:13:33 -0300 Subject: V4L/DVB (13934): tda8290: Fix FM radio easy programming standard selection for TDA8295 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda8290.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c index 19010f3d450..2833137fa81 100644 --- a/drivers/media/common/tuners/tda8290.c +++ b/drivers/media/common/tuners/tda8290.c @@ -144,7 +144,8 @@ static void set_audio(struct dvb_frontend *fe, } if (params->mode == V4L2_TUNER_RADIO) { - priv->tda8290_easy_mode = 0x01; /* Start with MN values */ + /* Set TDA8295 to FM radio; Start TDA8290 with MN values */ + priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01; tuner_dbg("setting to radio FM\n"); } else { tuner_dbg("setting tda829x to system %s\n", mode); -- cgit v1.2.3 From 30883ea8f2b489ccbb6aa0755832218ec45468a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 9 Jan 2010 20:44:06 -0300 Subject: V4L/DVB mx1_camera: don't check platform_get_irq's return value against zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq returns -ENXIO on failure, so !irq was probably always true. Better use (int)irq <= 0. Note that a return value of zero is still handled as error even though this could mean irq0. This is a followup to 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 that changed the return value of platform_get_irq from 0 to -ENXIO on error. Cc: David Vrabel Cc: Greg Kroah-Hartman Cc: Mauro Carvalho Chehab Cc: Guennadi Liakhovetski Cc: Antonio Ospite Cc: Paulius Zaleckas Cc: linux-media@vger.kernel.org Signed-off-by: Uwe Kleine-König Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mx1_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 2ba14fb5b03..c167cc3de49 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c @@ -718,7 +718,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || (int)irq <= 0) { err = -ENODEV; goto exit; } -- cgit v1.2.3 From b89fc2e5e7b6d6da3ab9a2dc05810794e5eac869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 9 Jan 2010 20:45:13 -0300 Subject: V4L/DVB sh_mobile_ceu: don't check platform_get_irq's return value against zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq returns -ENXIO on failure, so !irq was probably always true. Better use (int)irq <= 0. Note that a return value of zero is still handled as error even though this could mean irq0. This is a followup to 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 that changed the return value of platform_get_irq from 0 to -ENXIO on error. Cc: David Vrabel Cc: Greg Kroah-Hartman Cc: Mauro Carvalho Chehab Cc: Guennadi Liakhovetski Cc: Magnus Damm Cc: Kuninori Morimoto Cc: Paul Mundt Cc: linux-media@vger.kernel.org Signed-off-by: Uwe Kleine-König Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/sh_mobile_ceu_camera.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index d69363f0d8c..f09c7140d6b 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c @@ -1827,7 +1827,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || (int)irq <= 0) { dev_err(&pdev->dev, "Not enough CEU platform resources.\n"); err = -ENODEV; goto exit; -- cgit v1.2.3 From 21c91d2ee8b547e9661892d0532f69082c8a97aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20N=C3=A9meth?= Date: Sat, 9 Jan 2010 20:45:59 -0300 Subject: V4L/DVB (13941): rj54n1cb0c: remove compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the following compiler warning: 'dummy' is used uninitialized in this function. Although the result in the dummy variable is not used the program flow in soc_camera_limit_side() depends on the value in dummy. The program flow is better to be deterministic. Signed-off-by: Márton Németh Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/rj54n1cb0c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index 7e42989ce0e..805226e0d9c 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -563,7 +563,7 @@ static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) struct i2c_client *client = sd->priv; struct rj54n1 *rj54n1 = to_rj54n1(client); struct v4l2_rect *rect = &a->c; - unsigned int dummy, output_w, output_h, + unsigned int dummy = 0, output_w, output_h, input_w = rect->width, input_h = rect->height; int ret; -- cgit v1.2.3 From 423f5c0d016cd6b65c468d3dcdeeb708ee68074b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 28 Dec 2009 13:59:46 -0300 Subject: V4L/DVB (13955): cx25821: fix double unlock in medusa_video_init() medusa_set_videostandard() takes the lock but it always drops it before returning. This was found with a static checker and compile tested only. :/ Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/cx25821/cx25821-medusa-video.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c index e4df8134f05..1eb079b3d42 100644 --- a/drivers/staging/cx25821/cx25821-medusa-video.c +++ b/drivers/staging/cx25821/cx25821-medusa-video.c @@ -860,10 +860,8 @@ int medusa_video_init(struct cx25821_dev *dev) ret_val = medusa_set_videostandard(dev); - if (ret_val < 0) { - mutex_unlock(&dev->lock); + if (ret_val < 0) return -EINVAL; - } return 1; } -- cgit v1.2.3 From 08be64be3d1e5ecd72e7ba3147aea518e527f08e Mon Sep 17 00:00:00 2001 From: Dmitri Belimov Date: Fri, 8 Jan 2010 06:38:28 -0300 Subject: V4L/DVB (13966): DVB-T regression fix for saa7134 cards Some customers has problem with quality of DVB-T https://bugs.launchpad.net/ubuntu/+source/linux/+bug/446575 After this patch http://patchwork.kernel.org/patch/23345/ This is patch for fix regression with DVB-T. Tested with many people. Signed-off-by: Alexey Osipov Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 13 ------------- drivers/media/video/saa7134/saa7134-ts.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 9f85e917f9f..a7ad7810fdd 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -420,19 +420,6 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ctrl |= SAA7134_MAIN_CTRL_TE5; irq |= SAA7134_IRQ1_INTE_RA2_1 | SAA7134_IRQ1_INTE_RA2_0; - - /* dma: setup channel 5 (= TS) */ - - saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); - saa_writeb(SAA7134_TS_DMA1, - ((dev->ts.nr_packets - 1) >> 8) & 0xff); - /* TSNOPIT=0, TSCOLAP=0 */ - saa_writeb(SAA7134_TS_DMA2, - (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); - saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); - saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (dev->ts.pt_ts.dma >> 12)); } /* set task conditions + field handling */ diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index 03488ba4c99..b9817d74943 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -250,6 +250,19 @@ int saa7134_ts_start(struct saa7134_dev *dev) BUG_ON(dev->ts_started); + /* dma: setup channel 5 (= TS) */ + saa_writeb(SAA7134_TS_DMA0, (dev->ts.nr_packets - 1) & 0xff); + saa_writeb(SAA7134_TS_DMA1, + ((dev->ts.nr_packets - 1) >> 8) & 0xff); + /* TSNOPIT=0, TSCOLAP=0 */ + saa_writeb(SAA7134_TS_DMA2, + (((dev->ts.nr_packets - 1) >> 16) & 0x3f) | 0x00); + saa_writel(SAA7134_RS_PITCH(5), TS_PACKET_SIZE); + saa_writel(SAA7134_RS_CONTROL(5), SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->ts.pt_ts.dma >> 12)); + + /* reset hardware TS buffers */ saa_writeb(SAA7134_TS_SERIAL1, 0x00); saa_writeb(SAA7134_TS_SERIAL1, 0x03); saa_writeb(SAA7134_TS_SERIAL1, 0x00); -- cgit v1.2.3 From 41e840b13e111ba18b138d055ddd250bd5ad5e39 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 21:57:10 -0300 Subject: V4L/DVB (13699): [Mantis, MB86A16] Initial checkin: Mantis, MB86A16 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 1772 ++++++++++++++++++++++++++++ drivers/media/dvb/frontends/mb86a16.h | 38 + drivers/media/dvb/frontends/mb86a16_priv.h | 151 +++ drivers/media/dvb/mantis/Kconfig | 13 + drivers/media/dvb/mantis/Makefile | 7 + drivers/media/dvb/mantis/mantis_common.h | 135 +++ drivers/media/dvb/mantis/mantis_core.c | 215 ++++ drivers/media/dvb/mantis/mantis_core.h | 61 + drivers/media/dvb/mantis/mantis_dma.c | 238 ++++ drivers/media/dvb/mantis/mantis_dvb.c | 304 +++++ drivers/media/dvb/mantis/mantis_i2c.c | 189 +++ drivers/media/dvb/mantis/mantis_reg.h | 109 ++ drivers/media/dvb/mantis/mantis_vp1033.c | 151 +++ drivers/media/dvb/mantis/mantis_vp1033.h | 35 + drivers/media/dvb/mantis/mantis_vp1034.c | 52 + drivers/media/dvb/mantis/mantis_vp1034.h | 30 + drivers/media/dvb/mantis/mantis_vp2033.c | 73 ++ drivers/media/dvb/mantis/mantis_vp2033.h | 33 + drivers/media/dvb/mantis/mantis_vp3030.c | 53 + drivers/media/dvb/mantis/mantis_vp3030.h | 30 + 20 files changed, 3689 insertions(+) create mode 100644 drivers/media/dvb/frontends/mb86a16.c create mode 100644 drivers/media/dvb/frontends/mb86a16.h create mode 100644 drivers/media/dvb/frontends/mb86a16_priv.h create mode 100644 drivers/media/dvb/mantis/Kconfig create mode 100644 drivers/media/dvb/mantis/Makefile create mode 100644 drivers/media/dvb/mantis/mantis_common.h create mode 100644 drivers/media/dvb/mantis/mantis_core.c create mode 100644 drivers/media/dvb/mantis/mantis_core.h create mode 100644 drivers/media/dvb/mantis/mantis_dma.c create mode 100644 drivers/media/dvb/mantis/mantis_dvb.c create mode 100644 drivers/media/dvb/mantis/mantis_i2c.c create mode 100644 drivers/media/dvb/mantis/mantis_reg.h create mode 100644 drivers/media/dvb/mantis/mantis_vp1033.c create mode 100644 drivers/media/dvb/mantis/mantis_vp1033.h create mode 100644 drivers/media/dvb/mantis/mantis_vp1034.c create mode 100644 drivers/media/dvb/mantis/mantis_vp1034.h create mode 100644 drivers/media/dvb/mantis/mantis_vp2033.c create mode 100644 drivers/media/dvb/mantis/mantis_vp2033.h create mode 100644 drivers/media/dvb/mantis/mantis_vp3030.c create mode 100644 drivers/media/dvb/mantis/mantis_vp3030.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c new file mode 100644 index 00000000000..6a78a0c7403 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -0,0 +1,1772 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "mb86a16.h" +#include "mb86a16_priv.h" + +unsigned int verbose = 5; +module_param(verbose, int, 0644); + +#define ABS(x) ((x) < 0 ? (-x) : (x)) + +struct mb86a16_state { + struct i2c_adapter *i2c_adap; + const struct mb86a16_config *config; + struct dvb_frontend frontend; + u8 signal; + + // tuning parameters + int frequency; + int srate; + + // Internal stuff + int master_clk; + int deci; + int csel; + int rsel; +}; + +#define MB86A16_ERROR 0 +#define MB86A16_NOTICE 1 +#define MB86A16_INFO 2 +#define MB86A16_DEBUG 3 + +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > MB86A16_ERROR) && (x > y)) \ + printk(KERN_ERR "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_INFO) && (x > y)) \ + printk(KERN_INFO "%s: " format "\n", __func__, ##arg); \ + else if ((x > MB86A16_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg); \ + } else { \ + if (x > y) \ + printk(format, ##arg); \ + } \ +} while (0) + +#define TRACE_IN dprintk(verbose, MB86A16_DEBUG, 1, "-->()") +#define TRACE_OUT dprintk(verbose, MB86A16_DEBUG, 1, "()-->") + +static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val) +{ + int ret; + u8 buf[] = { reg, val }; + + struct i2c_msg msg = { + .addr = state->config->demod_address, + .flags = 0, + .buf = buf, + .len = 2 + }; + + dprintk(verbose, MB86A16_DEBUG, 1, + "writing to [0x%02x],Reg[0x%02x],Data[0x%02x]", + state->config->demod_address, buf[0], buf[1]); + + ret = i2c_transfer(state->i2c_adap, &msg, 1); + + return (ret != 1) ? -EREMOTEIO : 0; +} + +static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) +{ + int ret; + u8 b0[] = { reg }; + u8 b1[] = { 0 }; + + struct i2c_msg msg[] = { + { + .addr = state->config->demod_address, + .flags = 0, + .buf = b0, + .len = 1 + },{ + .addr = state->config->demod_address, + .flags = I2C_M_RD, + .buf = b1, + .len = 1 + } + }; + ret = i2c_transfer(state->i2c_adap, msg, 2); + if (ret != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)", + reg, ret); + + return -EREMOTEIO; + } + *val = b1[0]; + + return ret; +} + +static int CNTM_set(struct mb86a16_state *state, + unsigned char timint1, + unsigned char timint2, + unsigned char cnext) +{ + unsigned char val; + + val = (timint1 << 4) | (timint2 << 2) | cnext; + if (mb86a16_write(state, MB86A16_CNTMR, val) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int smrt_set(struct mb86a16_state *state, int rate) +{ + int tmp ; + int m ; + unsigned char STOFS0, STOFS1; + + m = 1 << state->deci; + tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk; + + STOFS0 = tmp & 0x0ff; + STOFS1 = (tmp & 0xf00) >> 8; + + if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) | + (state->csel << 1) | + state->rsel) < 0) + goto err; + if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0) + goto err; + if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -1; +} + +static int srst(struct mb86a16_state *state) +{ + if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + +} + +static int afcex_data_set(struct mb86a16_state *state, + unsigned char AFCEX_L, + unsigned char AFCEX_H) +{ + if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0) + goto err; + if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + + return -1; +} + +static int afcofs_data_set(struct mb86a16_state *state, + unsigned char AFCEX_L, + unsigned char AFCEX_H) +{ + if (mb86a16_write(state, 0x58, AFCEX_L) < 0) + goto err; + if (mb86a16_write(state, 0x59, AFCEX_H) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int stlp_set(struct mb86a16_state *state, + unsigned char STRAS, + unsigned char STRBS) +{ + if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA) +{ + if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0) + goto err; + if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int initial_set(struct mb86a16_state *state) +{ + if (stlp_set(state, 5, 7)) + goto err; + if (afcex_data_set(state, 0, 0)) + goto err; + if (afcofs_data_set(state, 0, 0)) + goto err; + + if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0) + goto err; + if (mb86a16_write(state, 0x2f, 0x21) < 0) + goto err; + if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0) + goto err; + if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0) + goto err; + if (mb86a16_write(state, 0x54, 0xff) < 0) + goto err; + if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int S01T_set(struct mb86a16_state *state, + unsigned char s1t, + unsigned s0t) +{ + if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + + +static int EN_set(struct mb86a16_state *state, + int cren, + int afcen) +{ + unsigned char val; + + val = 0x7a | (cren << 7) | (afcen << 2); + if (mb86a16_write(state, 0x49, val) < 0) + goto err; + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int AFCEXEN_set(struct mb86a16_state *state, + int afcexen, + int smrt) +{ + unsigned char AFCA ; + + if (smrt > 18875) + AFCA = 4; + else if (smrt > 9375) + AFCA = 3; + else if (smrt > 2250) + AFCA = 2; + else + AFCA = 1; + + if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int DAGC_data_set(struct mb86a16_state *state, + unsigned char DAGCA, + unsigned char DAGCW) +{ + if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static void smrt_info_get(struct mb86a16_state *state, int rate) +{ + if (rate >= 37501) { + state->deci = 0; state->csel = 0; state->rsel = 0; + } else if (rate >= 30001) { + state->deci = 0; state->csel = 0; state->rsel = 1; + } else if (rate >= 26251) { + state->deci = 0; state->csel = 1; state->rsel = 0; + } else if (rate >= 22501) { + state->deci = 0; state->csel = 1; state->rsel = 1; + } else if (rate >= 18751) { + state->deci = 1; state->csel = 0; state->rsel = 0; + } else if (rate >= 15001) { + state->deci = 1; state->csel = 0; state->rsel = 1; + } else if (rate >= 13126) { + state->deci = 1; state->csel = 1; state->rsel = 0; + } else if (rate >= 11251) { + state->deci = 1; state->csel = 1; state->rsel = 1; + } else if (rate >= 9376) { + state->deci = 2; state->csel = 0; state->rsel = 0; + } else if (rate >= 7501) { + state->deci = 2; state->csel = 0; state->rsel = 1; + } else if (rate >= 6563) { + state->deci = 2; state->csel = 1; state->rsel = 0; + } else if (rate >= 5626) { + state->deci = 2; state->csel = 1; state->rsel = 1; + } else if (rate >= 4688) { + state->deci = 3; state->csel = 0; state->rsel = 0; + } else if (rate >= 3751) { + state->deci = 3; state->csel = 0; state->rsel = 1; + } else if (rate >= 3282) { + state->deci = 3; state->csel = 1; state->rsel = 0; + } else if (rate >= 2814) { + state->deci = 3; state->csel = 1; state->rsel = 1; + } else if (rate >= 2344) { + state->deci = 4; state->csel = 0; state->rsel = 0; + } else if (rate >= 1876) { + state->deci = 4; state->csel = 0; state->rsel = 1; + } else if (rate >= 1641) { + state->deci = 4; state->csel = 1; state->rsel = 0; + } else if (rate >= 1407) { + state->deci = 4; state->csel = 1; state->rsel = 1; + } else if (rate >= 1172) { + state->deci = 5; state->csel = 0; state->rsel = 0; + } else if (rate >= 939) { + state->deci = 5; state->csel = 0; state->rsel = 1; + } else if (rate >= 821) { + state->deci = 5; state->csel = 1; state->rsel = 0; + } else { + state->deci = 5; state->csel = 1; state->rsel = 1; + } + + if (state->csel == 0) + state->master_clk = 92000; + else + state->master_clk = 61333; + +} + +static int signal_det(struct mb86a16_state *state, + int smrt, + unsigned char *SIG) +{ + + int ret ; + int smrtd ; + int wait_sym ; + int wait_t ; + unsigned char S[3] ; + int i ; + + if (*SIG > 45) { + if (CNTM_set(state, 2, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + wait_sym = 40000; + } else { + if (CNTM_set(state, 3, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + wait_sym = 80000; + } + for (i = 0; i < 3; i++) { + if (i == 0 ) + smrtd = smrt * 98 / 100; + else if (i == 1) + smrtd = smrt; + else + smrtd = smrt * 102 / 100; + smrt_info_get(state, smrtd); + smrt_set(state, smrtd); + srst(state); + wait_t = (wait_sym + 99 * smrtd / 100) / smrtd; + if (wait_t == 0) + wait_t = 1; + msleep_interruptible(10); + if (mb86a16_read(state, 0x37, &(S[i])) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + } + if ((S[1] > S[0] * 112 / 100) && + (S[1] > S[2] * 112 / 100)) { + + ret = 1; + } else { + ret = 0; + } + *SIG = S[1]; + + if (CNTM_set(state, 0, 1, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error"); + return -1; + } + + return ret; +} + +static int rf_val_set(struct mb86a16_state *state, + int f, + int smrt, + unsigned char R) +{ + unsigned char C, F, B; + int M; + unsigned char rf_val[5]; + int ack = -1; + + if (smrt > 37750 ) + C = 1; + else if (smrt > 18875) + C = 2; + else if (smrt > 5500 ) + C = 3; + else + C = 4; + + if (smrt > 30500) + F = 3; + else if (smrt > 9375) + F = 1; + else if (smrt > 4625) + F = 0; + else + F = 2; + + if (f < 1060) + B = 0; + else if (f < 1175) + B = 1; + else if (f < 1305) + B = 2; + else if (f < 1435) + B = 3; + else if (f < 1570) + B = 4; + else if (f < 1715) + B = 5; + else if (f < 1845) + B = 6; + else if (f < 1980) + B = 7; + else if (f < 2080) + B = 8; + else + B = 9; + + M = f * (1 << R) / 2; + + rf_val[0] = 0x01 | (C << 3) | (F << 1); + rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12); + rf_val[2] = (M & 0x00ff0) >> 4; + rf_val[3] = ((M & 0x0000f) << 4) | B; + + // Frequency Set + if (mb86a16_write(state, 0x21, rf_val[0]) < 0) + ack = 0; + if (mb86a16_write(state, 0x22, rf_val[1]) < 0) + ack = 0; + if (mb86a16_write(state, 0x23, rf_val[2]) < 0) + ack = 0; + if (mb86a16_write(state, 0x24, rf_val[3]) < 0) + ack = 0; + if (mb86a16_write(state, 0x25, 0x01) < 0) + ack = 0; + if (ack == 0) { + dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int afcerr_chk(struct mb86a16_state *state) +{ + unsigned char AFCM_L, AFCM_H ; + int AFCM ; + int afcm, afcerr ; + + if (mb86a16_read(state, 0x0e, &AFCM_L) != 2) + goto err; + if (mb86a16_read(state, 0x0f, &AFCM_H) != 2) + goto err; + + AFCM = (AFCM_H << 8) + AFCM_L; + + if (AFCM > 2048) + afcm = AFCM - 4096; + else + afcm = AFCM; + afcerr = afcm * state->master_clk / 8192; + + return afcerr; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int dagcm_val_get(struct mb86a16_state *state) +{ + int DAGCM; + unsigned char DAGCM_H, DAGCM_L; + + if (mb86a16_read(state, 0x45, &DAGCM_L) != 2) + goto err; + if (mb86a16_read(state, 0x46, &DAGCM_H) != 2) + goto err; + + DAGCM = (DAGCM_H << 8) + DAGCM_L; + + return DAGCM; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + if (state->signal & 0x02) + *status |= FE_HAS_VITERBI; + if (state->signal & 0x01) + *status |= FE_HAS_SYNC; + if (state->signal & 0x03) + *status |= FE_HAS_LOCK; + + return 0; +} + +static int sync_chk(struct mb86a16_state *state, + unsigned char *VIRM) +{ + unsigned char val; + int sync; + + if (mb86a16_read(state, 0x0d, &val) != 2) + goto err; + + dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val); + sync = val & 0x01; + *VIRM = (val & 0x1c) >> 2; + + return sync; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + +} + +static int freqerr_chk(struct mb86a16_state *state, + int fTP, + int smrt, + int unit) +{ + unsigned char CRM, AFCML, AFCMH; + unsigned char temp1, temp2, temp3; + int crm, afcm, AFCM; + int crrerr, afcerr; // [kHz] + int frqerr; // [MHz] + int afcen, afcexen = 0; + int R, M, fOSC, fOSC_OFS; + + if (mb86a16_read(state, 0x43, &CRM) != 2) + goto err; + + if (CRM > 127) + crm = CRM - 256; + else + crm = CRM; + + crrerr = smrt * crm / 256; + if (mb86a16_read(state, 0x49, &temp1) != 2) + goto err; + + afcen = (temp1 & 0x04) >> 2; + if (afcen == 0) { + if (mb86a16_read(state, 0x2a, &temp1) != 2) + goto err; + afcexen = (temp1 & 0x20) >> 5; + } + + if (afcen == 1) { + if (mb86a16_read(state, 0x0e, &AFCML) != 2) + goto err; + if (mb86a16_read(state, 0x0f, &AFCMH) != 2) + goto err; + } else if (afcexen == 1) { + if (mb86a16_read(state, 0x2b, &AFCML) != 2) + goto err; + if (mb86a16_read(state, 0x2c, &AFCMH) != 2) + goto err; + } + if ((afcen == 1) || (afcexen == 1)) { + smrt_info_get(state, smrt); + AFCM = ((AFCMH & 0x01) << 8) + AFCML; + if (AFCM > 255) + afcm = AFCM - 512; + else + afcm = AFCM; + + afcerr = afcm * state->master_clk / 8192; + } else + afcerr = 0; + + if (mb86a16_read(state, 0x22, &temp1) != 2) + goto err; + if (mb86a16_read(state, 0x23, &temp2) != 2) + goto err; + if (mb86a16_read(state, 0x24, &temp3) != 2) + goto err; + + R = (temp1 & 0xe0) >> 5; + M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4); + if (R == 0) + fOSC = 2 * M; + else + fOSC = M; + + fOSC_OFS = fOSC - fTP; + + if (unit == 0) { //[MHz] + if (crrerr + afcerr + fOSC_OFS * 1000 >= 0) + frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000; + else + frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000; + } else { //[kHz] + frqerr = crrerr + afcerr + fOSC_OFS * 1000; + } + + return frqerr; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt) +{ + unsigned char R; + + if (smrt > 9375) + R = 0; + else + R = 1; + + return R; +} + +static void swp_info_get(struct mb86a16_state *state, + int fOSC_start, + int smrt, + int v, int R, + int swp_ofs, + int *fOSC, + int *afcex_freq, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + int crnt_swp_freq ; + + crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs; + + if (R == 0 ) + *fOSC = (crnt_swp_freq + 1000) / 2000 * 2; + else + *fOSC = (crnt_swp_freq + 500) / 1000; + + if (*fOSC >= crnt_swp_freq) + *afcex_freq = *fOSC *1000 - crnt_swp_freq; + else + *afcex_freq = crnt_swp_freq - *fOSC * 1000; + + AFCEX = *afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + + +static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V, int vmax, int vmin, + int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1) +{ + int swp_freq ; + + if ((i % 2 == 1) && (v <= vmax)) { + // positive v (case 1) + if ((v - 1 == vmin) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v - 1) > *(V + 30 + v)) && + (*(V + 30 + v - 1) > SIGMIN)) { + + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } else if ((v == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v) > *(V + 30 + v - 1)) && + (*(V + 30 + v) > SIGMIN)) { + // (case 2) + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else if ((*(V + 30 + v) > 0) && + (*(V + 30 + v - 1) > 0) && + (*(V + 30 + v - 2) > 0) && + (*(V + 30 + v - 3) > 0) && + (*(V + 30 + v - 1) > *(V + 30 + v)) && + (*(V + 30 + v - 2) > *(V + 30 + v - 3)) && + ((*(V + 30 + v - 1) > SIGMIN) || + (*(V + 30 + v - 2) > SIGMIN))) { + // (case 3) + if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2; + *SIG1 = *(V + 30 + v - 2); + } + } else if ((v == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v - 1) >= 0) && + (*(V + 30 + v - 2) >= 0) && + (*(V + 30 + v) > *(V + 30 + v - 2)) && + (*(V + 30 + v - 1) > *(V + 30 + v - 2)) && + ((*(V + 30 + v) > SIGMIN) || + (*(V + 30 + v - 1) > SIGMIN))) { + // (case 4) + if (*(V + 30 + v) >= *(V + 30 + v - 1)) { + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else { + swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; + *SIG1 = *(V + 30 + v - 1); + } + } else { + swp_freq = -1 ; + } + } else if ((i % 2 == 0) && (v >= vmin)) { + // Negative v (case 1) + if ((*(V + 30 + v) > 0) && + (*(V + 30 + v + 1) > 0) && + (*(V + 30 + v + 2) > 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && + (*(V + 30 + v + 1) > SIGMIN)) { + + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else if ((v + 1 == vmax) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 1) > SIGMIN)) { + // (case 2) + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v); + } else if ((v == vmin) && + (*(V + 30 + v) > 0) && + (*(V + 30 + v + 1) > 0) && + (*(V + 30 + v + 2) > 0) && + (*(V + 30 + v) > *(V + 30 + v + 1)) && + (*(V + 30 + v) > *(V + 30 + v + 2)) && + (*(V + 30 + v) > SIGMIN)) { + // (case 3) + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else if ((*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V +30 + v + 3) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 2) > *(V + 30 + v + 3)) && + ((*(V + 30 + v + 1) > SIGMIN) || + (*(V + 30 + v + 2) > SIGMIN))) { + // (case 4) + if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; + *SIG1 = *(V + 30 + v + 2); + } + } else if ((*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V + 30 + v + 3) >= 0) && + (*(V + 30 + v) > *(V + 30 + v + 2)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 2)) && + (*(V + 30 + v) > *(V + 30 + v + 3)) && + (*(V + 30 + v + 1) > *(V + 30 + v + 3)) && + ((*(V + 30 + v) > SIGMIN) || + (*(V + 30 + v + 1) > SIGMIN))) { + // (case 5) + if (*(V + 30 + v) >= *(V + 30 + v + 1)) { + swp_freq = fOSC * 1000 + afcex_freq; + *SIG1 = *(V + 30 + v); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } + } else if ((v + 2 == vmin) && + (*(V + 30 + v) >= 0) && + (*(V + 30 + v + 1) >= 0) && + (*(V + 30 + v + 2) >= 0) && + (*(V + 30 + v + 1) > *(V + 30 + v)) && + (*(V + 30 + v + 2) > *(V + 30 + v)) && + ((*(V + 30 + v + 1) > SIGMIN) || + (*(V + 30 + v + 2) > SIGMIN))) { + // (case 6) + if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; + *SIG1 = *(V + 30 + v + 1); + } else { + swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2; + *SIG1 = *(V + 30 + v + 2); + } + } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) { + swp_freq = fOSC * 1000; + *SIG1 = *(V + 30 + v); + } else swp_freq = -1; + } else swp_freq = -1; + + return swp_freq; +} + +static void swp_info_get2(struct mb86a16_state *state, + int smrt, + int R, + int swp_freq, + int *afcex_freq, + int *fOSC, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + + if (R == 0) + *fOSC = (swp_freq + 1000) / 2000 * 2; + else + *fOSC = (swp_freq + 500) / 1000; + + if (*fOSC >= swp_freq) + *afcex_freq = *fOSC * 1000 - swp_freq; + else + *afcex_freq = swp_freq - *fOSC * 1000; + + AFCEX = *afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + +static void afcex_info_get(struct mb86a16_state *state, + int afcex_freq, + unsigned char *AFCEX_L, + unsigned char *AFCEX_H) +{ + int AFCEX ; + + AFCEX = afcex_freq * 8192 / state->master_clk; + *AFCEX_L = AFCEX & 0x00ff; + *AFCEX_H = (AFCEX & 0x0f00) >> 8; +} + +static int SEQ_set(struct mb86a16_state *state, unsigned char loop) +{ + // SLOCK0 = 0 + if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV) +{ + // Viterbi Rate, IQ Settings + if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int FEC_srst(struct mb86a16_state *state) +{ + if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int S2T_set(struct mb86a16_state *state, unsigned char S2T) +{ + if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + +static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T) +{ + if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + return 0; +} + + +static int mb86a16_set_fe(struct mb86a16_state *state) +{ + u8 agcval, cnmval; + + int i, j; + int fOSC = 0; + int fOSC_start = 0; + int wait_t; + int fcp; + int swp_ofs; + int V[60]; + u8 SIG1MIN; + + unsigned char CREN, AFCEN, AFCEXEN; + unsigned char SIG1; + unsigned char TIMINT1, TIMINT2, TIMEXT; + unsigned char S0T, S1T; + unsigned char S2T; +// unsigned char S2T, S3T; + unsigned char S4T, S5T; + unsigned char AFCEX_L, AFCEX_H; + unsigned char R; + unsigned char VIRM; + unsigned char ETH, VIA; + unsigned char junk; + + int loop; + int ftemp; + int v, vmax, vmin; + int vmax_his, vmin_his; + int swp_freq, prev_swp_freq[20]; + int prev_freq_num; + int signal_dupl; + int afcex_freq; + int signal; + int afcerr; + int temp_freq, delta_freq; + int dagcm[4]; + int smrt_d; +// int freq_err; + int n; + int ret = -1; + int sync; + + dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate); + + fcp = 5000; // (carrier recovery [kHz]) +// fcp = 3000; + swp_ofs = state->srate / 4; + + for (i = 0; i < 60; i++) + V[i] = -1; + + for (i = 0; i < 20; i++) + prev_swp_freq[i] = 0; + + SIG1MIN = 25; + + for (n = 0; ((n < 3) && (ret == -1)); n++) { + SEQ_set(state, 0); + iq_vt_set(state, 0); + + CREN = 0; + AFCEN = 0; + AFCEXEN = 1; + TIMINT1 = 0; + TIMINT2 = 1; + TIMEXT = 2; + S1T = 0; + S0T = 0; + + if (initial_set(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "initial set failed"); + return -1; + } + if (DAGC_data_set(state, 3, 2) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; // (0, 0) + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; // (1, smrt) = (1, symbolrate) + } + if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error"); + return -1; // (0, 1, 2) + } + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; // (0, 0) + } + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error"); + return -1; + } + + R = vco_dev_get(state, state->srate); + if (R == 1) + fOSC_start = state->frequency; + + else if (R == 0) { + if (state->frequency % 2 == 0) { + fOSC_start = state->frequency; + } else { + fOSC_start = state->frequency + 1; + if (fOSC_start > 2150) + fOSC_start = state->frequency - 1; + } + } + loop = 1; + ftemp = fOSC_start * 1000; + vmax = 0 ; + while (loop == 1) { + ftemp = ftemp + swp_ofs; + vmax++; + + // Upper bound + if (ftemp > 2150000) { + loop = 0; + vmax--; + } + else if ((ftemp == 2150000) || (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) + loop = 0; + } + + loop = 1; + ftemp = fOSC_start * 1000; + vmin = 0 ; + while (loop == 1) { + ftemp = ftemp - swp_ofs; + vmin--; + + // Lower bound + if (ftemp < 950000) { + loop = 0; + vmin++; + } + else if ((ftemp == 950000) || (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) + loop = 0; + } + + wait_t = (8000 + state->srate / 2) / state->srate; + if (wait_t == 0) + wait_t = 1; + + i = 0; + j = 0; + prev_freq_num = 0; + loop = 1; + signal = 0; + vmax_his = 0; + vmin_his = 0; + v = 0; + + while (loop == 1) { + swp_info_get(state, fOSC_start, state->srate, + v, R, swp_ofs, &fOSC, + &afcex_freq, &AFCEX_L, &AFCEX_H); + + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + msleep_interruptible(wait_t); + + if (mb86a16_read(state, 0x37, &SIG1) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -1; + } + V[30 + v] = SIG1 ; + swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin, + SIG1MIN, fOSC, afcex_freq, + swp_ofs, &SIG1); //changed + + signal_dupl = 0; + for (j = 0; j < prev_freq_num; j++) { + if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) { + signal_dupl = 1; + dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j); + } + } + if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) { + dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate); + prev_swp_freq[prev_freq_num] = swp_freq; + prev_freq_num++; + swp_info_get2(state, state->srate, R, swp_freq, + &afcex_freq, &fOSC, + &AFCEX_L, &AFCEX_H); + + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + signal = signal_det(state, state->srate, &SIG1); + if (signal == 1) { + dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****"); + loop = 0; + } else { + dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again..."); + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + } + } + if (v > vmax) + vmax_his = 1 ; + if (v < vmin) + vmin_his = 1 ; + i++; + + if ((i % 2 == 1) && (vmax_his == 1)) + i++; + if ((i % 2 == 0) && (vmin_his == 1)) + i++; + + if (i % 2 == 1) + v = (i + 1) / 2; + else + v = -i / 2; + + if ((vmax_his == 1) && (vmin_his == 1)) + loop = 0 ; + } + + if (signal == 1) { + dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check"); + S1T = 7 ; + S0T = 1 ; + CREN = 0 ; + AFCEN = 1 ; + AFCEXEN = 0 ; + + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; + } + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H); + if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + // delay 4~200 + wait_t = 200000 / state->master_clk + 200000 / state->srate; + msleep(wait_t); + afcerr = afcerr_chk(state); + if (afcerr == -1) + return -1; + + swp_freq = fOSC * 1000 + afcerr ; + AFCEXEN = 1 ; + if (state->srate >= 1500) + smrt_d = state->srate / 3; + else + smrt_d = state->srate / 2; + smrt_info_get(state, smrt_d); + if (smrt_set(state, smrt_d) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + R = vco_dev_get(state, smrt_d); + if (DAGC_data_set(state, 2, 0) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + for (i = 0; i < 3; i++) { + temp_freq = swp_freq + (i - 1) * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[i] = dagcm_val_get(state); + } + if ((dagcm[0] > dagcm[1]) && + (dagcm[0] > dagcm[2]) && + (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) { + + temp_freq = swp_freq - 2 * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[3] = dagcm_val_get(state); + if (dagcm[3] > dagcm[1]) + delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300; + else + delta_freq = 0; + } else if ((dagcm[2] > dagcm[1]) && + (dagcm[2] > dagcm[0]) && + (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) { + + temp_freq = swp_freq + 2 * state->srate / 8; + swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, smrt_d, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set"); + return -1; + } + wait_t = 200000 / state->master_clk + 40000 / smrt_d; + msleep(wait_t); + dagcm[3] = dagcm_val_get(state); + if (dagcm[3] > dagcm[1]) + delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300; + else + delta_freq = 0 ; + + } else { + delta_freq = 0 ; + } + dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq); + swp_freq += delta_freq; + dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq); + if (ABS(state->frequency * 1000 - swp_freq) > 3800) { + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL !"); + } else { + + S1T = 0; + S0T = 3; + CREN = 1; + AFCEN = 0; + AFCEXEN = 1; + + if (S01T_set(state, S1T, S0T) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); + return -1; + } + if (DAGC_data_set(state, 0, 0) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error"); + return -1; + } + R = vco_dev_get(state, state->srate); + smrt_info_get(state, state->srate); + if (smrt_set(state, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "smrt set error"); + return -1; + } + if (EN_set(state, CREN, AFCEN) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); + return -1; + } + if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); + return -1; + } + swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H); + if (rf_val_set(state, fOSC, state->srate, R) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); + return -1; + } + if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); + return -1; + } + if (srst(state) < 0) { + dprintk(verbose, MB86A16_ERROR, 1, "srst error"); + return -1; + } + wait_t = 7 + (10000 + state->srate / 2) / state->srate; + if (wait_t == 0) + wait_t = 1; + msleep_interruptible(wait_t); + if (mb86a16_read(state, 0x37, &SIG1) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + if (SIG1 > 110) { + S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6; + wait_t = 7 + (917504 + state->srate / 2) / state->srate; + } else if (SIG1 > 105) { + S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1048576 + state->srate / 2) / state->srate; + } else if (SIG1 > 85) { + S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1310720 + state->srate / 2) / state->srate; + } else if (SIG1 > 65) { + S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (1572864 + state->srate / 2) / state->srate; + } else { + S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; + wait_t = 7 + (2097152 + state->srate / 2) / state->srate; + } + S2T_set(state, S2T); + S45T_set(state, S4T, S5T); + Vi_set(state, ETH, VIA); + srst(state); + msleep_interruptible(wait_t); + sync = sync_chk(state, &VIRM); + dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); + if (mb86a16_read(state, 0x0d, &state->signal) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + if (VIRM) { + if (VIRM == 4) { // 5/6 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + if (state->srate < 5000) + // FIXME ! , should be a long wait ! + msleep_interruptible(wait_t); + else + msleep_interruptible(wait_t); + + if (sync_chk(state, &junk) == 0) { + iq_vt_set(state, 1); + FEC_srst(state); + } + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + + msleep_interruptible(wait_t); + SEQ_set(state, 1); + } else { // 1/2, 2/3, 3/4, 7/8 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + + msleep_interruptible(wait_t); + SEQ_set(state, 1); + } + } else { + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + SEQ_set(state, 1); + } + } + } else { + dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + } + + sync = sync_chk(state, &junk); + if (sync) { + dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); + freqerr_chk(state, state->frequency, state->srate, 1); + } + } + + mb86a16_read(state, 0x15, &agcval); + mb86a16_read(state, 0x26, &cnmval); + dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval); + + return ret; +} + +static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe, + struct dvb_diseqc_master_cmd *cmd) +{ + struct mb86a16_state *state = fe->demodulator_priv; + int i; + u8 regs; + + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) + goto err; + + regs = 0x18; + + if (cmd->msg_len > 5 || cmd->msg_len < 4) + return -EINVAL; + + for (i = 0; i < cmd->msg_len; i++) { + if (mb86a16_write(state, regs, cmd->msg[i]) < 0) + goto err; + + regs++; + } + i += 0x90; + + msleep_interruptible(10); + + if (mb86a16_write(state, MB86A16_DCC1, i) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + switch (burst) { + case SEC_MINI_A: + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_TBEN | + MB86A16_DCC1_TBO) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + case SEC_MINI_B: + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_TBEN) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + } + + return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) +{ + struct mb86a16_state *state = fe->demodulator_priv; + + switch (tone) { + case SEC_TONE_ON: + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA | + MB86A16_DCC1_CTOE) < 0) + + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0) + goto err; + break; + case SEC_TONE_OFF: + if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0) + goto err; + if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0) + goto err; + break; + default: + return -EINVAL; + } + return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; +} + +#define MB86A16_FE_ALGO 1 + +static int mb86a16_frontend_algo(struct dvb_frontend *fe) +{ + return MB86A16_FE_ALGO; +} + +static int mb86a16_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p, + unsigned int mode_flags, + int *delay, + fe_status_t *status) +{ + int ret = 0; + struct mb86a16_state *state = fe->demodulator_priv; + + if (p != NULL) { + state->frequency = p->frequency / 1000; + state->srate = p->u.qpsk.symbol_rate / 1000; + ret = mb86a16_set_fe(state); + } + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + mb86a16_read_status(fe, status); + + *delay = HZ/3000; + + return ret; +} + +static void mb86a16_release(struct dvb_frontend *fe) +{ + struct mb86a16_state *state = fe->demodulator_priv; + kfree(state); +} + +static int mb86a16_init(struct dvb_frontend *fe) +{ + return 0; +} + +static int mb86a16_sleep(struct dvb_frontend *fe) +{ + return 0; +} + +static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) +{ + return 0; +} + +static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + *strength = 0; + + return 0; +} + +struct cnr { + u8 cn_reg; + u8 cn_val; +}; + +static const struct cnr cnr_tab[] = { + { 35, 2 }, + { 40, 3 }, + { 50, 4 }, + { 60, 5 }, + { 70, 6 }, + { 80, 7 }, + { 92, 8 }, + { 103, 9 }, + { 115, 10 }, + { 138, 12 }, + { 162, 15 }, + { 180, 18 }, + { 185, 19 }, + { 189, 20 }, + { 195, 22 }, + { 199, 24 }, + { 201, 25 }, + { 202, 26 }, + { 203, 27 }, + { 205, 28 }, + { 208, 30 } +}; + +static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct mb86a16_state *state = fe->demodulator_priv; + int i = 0; + int low_tide = 2, high_tide = 30, q_level; + u8 cn; + + if (mb86a16_read(state, 0x26, &cn) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) { + if (cn < cnr_tab[i].cn_reg) { + *snr = cnr_tab[i].cn_val; + break; + } + } + q_level = (*snr * 100) / (high_tide - low_tide); + dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); + + return 0; +} + +static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) +{ + return 0; +} + +static struct dvb_frontend_ops mb86a16_ops = { + .info = { + .name = "Fujitsu MB86A16 DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, + .frequency_tolerance = 0, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | FE_CAN_QPSK | + FE_CAN_FEC_AUTO + }, + .release = mb86a16_release, + .tune = mb86a16_set_frontend, + .read_status = mb86a16_read_status, + .get_frontend_algo = mb86a16_frontend_algo, + .init = mb86a16_init, + .sleep = mb86a16_sleep, + .read_status = mb86a16_read_status, + + .read_ber = mb86a16_read_ber, + .read_signal_strength = mb86a16_read_signal_strength, + .read_snr = mb86a16_read_snr, + .read_ucblocks = mb86a16_read_ucblocks, + + .diseqc_send_master_cmd = mb86a16_send_diseqc_msg, + .diseqc_send_burst = mb86a16_send_diseqc_burst, + .set_tone = mb86a16_set_tone, +}; + +struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap) +{ + u8 dev_id = 0; + struct mb86a16_state *state = NULL; + + state = kmalloc(sizeof (struct mb86a16_state), GFP_KERNEL); + if (state == NULL) + goto error; + + state->config = config; + state->i2c_adap = i2c_adap; + + mb86a16_read(state, 0x7f, &dev_id); + if (dev_id != 0xfe) + goto error; + + memcpy(&state->frontend.ops, &mb86a16_ops, sizeof (struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + state->frontend.ops.set_voltage = state->config->set_voltage; + + return &state->frontend; +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(mb86a16_attach); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Manu Abraham"); diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h new file mode 100644 index 00000000000..b7545d0343f --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -0,0 +1,38 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MB86A16_H +#define __MB86A16_H + +#include +#include "dvb_frontend.h" + + +struct mb86a16_config { + u8 demod_address; + + int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); +}; + +extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap); + + +#endif //__MB86A16_H diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h new file mode 100644 index 00000000000..5de57006806 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a16_priv.h @@ -0,0 +1,151 @@ +/* + Fujitsu MB86A16 DVB-S/DSS DC Receiver driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MB86A16_PRIV_H +#define __MB86A16_PRIV_H + +#define MB86A16_TSOUT 0x00 +#define MB86A16_TSOUT_HIZSEL (0x01 << 5) +#define MB86A16_TSOUT_HIZCNTI (0x01 << 4) +#define MB86A16_TSOUT_MODE (0x01 << 3) +#define MB86A16_TSOUT_ORDER (0x01 << 2) +#define MB86A16_TSOUT_ERROR (0x01 << 1) +#define Mb86A16_TSOUT_EDGE (0x01 << 0) + +#define MB86A16_FEC 0x01 +#define MB86A16_FEC_FSYNC (0x01 << 5) +#define MB86A16_FEC_PCKB8 (0x01 << 4) +#define MB86A16_FEC_DVDS (0x01 << 3) +#define MB86A16_FEC_EREN (0x01 << 2) +#define Mb86A16_FEC_RSEN (0x01 << 1) +#define MB86A16_FEC_DIEN (0x01 << 0) + +#define MB86A16_AGC 0x02 +#define MB86A16_AGC_AGMD (0x01 << 6) +#define MB86A16_AGC_AGCW (0x0f << 2) +#define MB86A16_AGC_AGCP (0x01 << 1) +#define MB86A16_AGC_AGCR (0x01 << 0) + +#define MB86A16_SRATE1 0x03 +#define MB86A16_SRATE1_DECI (0x07 << 2) +#define MB86A16_SRATE1_CSEL (0x01 << 1) +#define MB86A16_SRATE1_RSEL (0x01 << 0) + +#define MB86A16_SRATE2 0x04 +#define MB86A16_SRATE2_STOFSL (0xff << 0) + +#define MB86A16_SRATE3 0x05 +#define MB86A16_SRATE2_STOFSH (0xff << 0) + +#define MB86A16_VITERBI 0x06 +#define MB86A16_FRAMESYNC 0x07 +#define MB86A16_CRLFILTCOEF1 0x08 +#define MB86A16_CRLFILTCOEF2 0x09 +#define MB86A16_STRFILTCOEF1 0x0a +#define MB86A16_STRFILTCOEF2 0x0b +#define MB86A16_RESET 0x0c +#define MB86A16_STATUS 0x0d +#define MB86A16_AFCML 0x0e +#define MB86A16_AFCMH 0x0f +#define MB86A16_BERMON 0x10 +#define MB86A16_BERTAB 0x11 +#define MB86A16_BERLSB 0x12 +#define MB86A16_BERMID 0x13 +#define MB86A16_BERMSB 0x14 +#define MB86A16_AGCM 0x15 + +#define MB86A16_DCC1 0x16 +#define MB86A16_DCC1_DISTA (0x01 << 7) +#define MB86A16_DCC1_PRTY (0x01 << 6) +#define MB86A16_DCC1_CTOE (0x01 << 5) +#define MB86A16_DCC1_TBEN (0x01 << 4) +#define MB86A16_DCC1_TBO (0x01 << 3) +#define MB86A16_DCC1_NUM (0x07 << 0) + +#define MB86A16_DCC2 0x17 +#define MB86A16_DCC2_DCBST (0x01 << 0) + +#define MB86A16_DCC3 0x18 +#define MB86A16_DCC3_CODE0 (0xff << 0) + +#define MB86A16_DCC4 0x19 +#define MB86A16_DCC4_CODE1 (0xff << 0) + +#define MB86A16_DCC5 0x1a +#define MB86A16_DCC5_CODE2 (0xff << 0) + +#define MB86A16_DCC6 0x1b +#define MB86A16_DCC6_CODE3 (0xff << 0) + +#define MB86A16_DCC7 0x1c +#define MB86A16_DCC7_CODE4 (0xff << 0) + +#define MB86A16_DCC8 0x1d +#define MB86A16_DCC8_CODE5 (0xff << 0) + +#define MB86A16_DCCOUT 0x1e +#define MB86A16_DCCOUT_DISEN (0x01 << 0) + +#define MB86A16_TONEOUT1 0x1f +#define MB86A16_TONE_TDIVL (0xff << 0) + +#define MB86A16_TONEOUT2 0x20 +#define MB86A16_TONE_TMD (0x03 << 2) +#define MB86A16_TONE_TDIVH (0x03 << 0) + +#define MB86A16_FREQ1 0x21 +#define MB86A16_FREQ2 0x22 +#define MB86A16_FREQ3 0x23 +#define MB86A16_FREQ4 0x24 +#define MB86A16_FREQSET 0x25 +#define MB86A16_CNM 0x26 +#define MB86A16_PORT0 0x27 +#define MB86A16_PORT1 0x28 +#define MB86A16_DRCFILT 0x29 +#define MB86A16_AFC 0x2a +#define MB86A16_AFCEXL 0x2b +#define MB86A16_AFCEXH 0x2c +#define MB86A16_DAGC 0x2d +#define MB86A16_SEQMODE 0x32 +#define MB86A16_S0S1T 0x33 +#define MB86A16_S2S3T 0x34 +#define MB86A16_S4S5T 0x35 +#define MB86A16_CNTMR 0x36 +#define MB86A16_SIG1 0x37 +#define MB86A16_SIG2 0x38 +#define MB86A16_VIMAG 0x39 +#define MB86A16_VISET1 0x3a +#define MB86A16_VISET2 0x3b +#define MB86A16_VISET3 0x3c +#define MB86A16_FAGCS1 0x3d +#define MB86A16_FAGCS2 0x3e +#define MB86A16_FAGCS3 0x3f +#define MB86A16_FAGCS4 0x40 +#define MB86A16_FAGCS5 0x41 +#define MB86A16_FAGCS6 0x42 +#define MB86A16_CRM 0x43 +#define MB86A16_STRM 0x44 +#define MB86A16_DAGCML 0x45 +#define MB86A16_DAGCMH 0x46 +#define MB86A16_QPSKTST 0x49 +#define MB86A16_DISTMON 0x52 +#define MB86A16_VERSION 0x7f + +#endif //__MB86A16_PRIV_H diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig new file mode 100644 index 00000000000..4ba16d0ad96 --- /dev/null +++ b/drivers/media/dvb/mantis/Kconfig @@ -0,0 +1,13 @@ +config DVB_MANTIS + tristate "MANTIS based cards" + depends on DVB_CORE && PCI && I2C + select DVB_MB86A16 + select DVB_CU1216 + select DVB_ZL10353 + select DVB_STV0299 + select DVB_PLL + help + Support for PCI cards based on the Mantis PCI bridge. + Say Y when you have a Mantis based DVB card and want to use it. + + If unsure say N. diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile new file mode 100644 index 00000000000..a980ff2382b --- /dev/null +++ b/drivers/media/dvb/mantis/Makefile @@ -0,0 +1,7 @@ +mantis-objs = mantis_core.o mantis_dma.o mantis_pci.o mantis_i2c.o \ + mantis_dvb.o mantis_vp1033.o mantis_vp1034.o mantis_vp2033.o \ + mantis_vp3030.o + +obj-$(CONFIG_DVB_MANTIS) += mantis.o + +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h new file mode 100644 index 00000000000..ba360f88496 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -0,0 +1,135 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_COMMON_H +#define __MANTIS_COMMON_H + +#include +#include +#include +#include + +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dmxdev.h" +#include "dvb_frontend.h" +#include "dvb_net.h" +#include +#include "mantis_reg.h" + +#define MANTIS_ERROR 0 +#define MANTIS_NOTICE 1 +#define MANTIS_INFO 2 +#define MANTIS_DEBUG 3 + +#define dprintk(x, y, z, format, arg...) do { \ + if (z) { \ + if ((x > MANTIS_ERROR) && (x > y)) \ + printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_NOTICE) && (x > y)) \ + printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_INFO) && (x > y)) \ + printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((x > MANTIS_DEBUG) && (x > y)) \ + printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + } else { \ + if (x > y) \ + printk(format , ##arg); \ + } \ +} while(0) + +#define mwrite(dat, addr) writel((dat), addr) +#define mread(addr) readl(addr) + +#define mmwrite(dat, addr) mwrite((dat), (mantis->mantis_mmio + (addr))) +#define mmread(addr) mread(mantis->mantis_mmio + (addr)) +#define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) +#define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) +#define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) + + +struct mantis_pci { + /* PCI stuff */ + u16 vendor_id; + u16 device_id; + u8 latency; + + struct pci_dev *pdev; + + unsigned long mantis_addr; + volatile void __iomem *mantis_mmio; + + u8 irq; + u8 revision; + + unsigned int num; + u16 ts_size; + + /* RISC Core */ + u32 finished_block; + u32 last_block; + u32 line_bytes; + u32 line_count; + u32 risc_pos; + u8 *buf_cpu; + dma_addr_t buf_dma; + u32 *risc_cpu; + dma_addr_t risc_dma; + + struct tasklet_struct tasklet; + + struct i2c_adapter adapter; + int i2c_rc; + wait_queue_head_t i2c_wq; + + /* DVB stuff */ + struct dvb_adapter dvb_adapter; + struct dvb_frontend *fe; + struct dvb_demux demux; + struct dmxdev dmxdev; + struct dmx_frontend fe_hw; + struct dmx_frontend fe_mem; + struct dvb_net dvbnet; + + u8 feeds; + + struct mantis_config *config; + + u32 mantis_int_stat; + u32 mantis_int_mask; + + /* board specific */ + u8 mac_address[8]; + u32 sub_vendor_id; + u32 sub_device_id; + + /* A12 A13 A14 */ + int gpio_status;}; + +extern unsigned int verbose; +extern unsigned int devs; +extern unsigned int i2c; +extern int mantis_dvb_init(struct mantis_pci *mantis); +extern int mantis_frontend_init(struct mantis_pci *mantis); +extern int mantis_dvb_exit(struct mantis_pci *mantis); +extern void mantis_dma_xfer(unsigned long data); +extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); + +#endif //__MANTIS_COMMON_H diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c new file mode 100644 index 00000000000..11122775245 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -0,0 +1,215 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_core.h" + + +static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + int err; + struct i2c_msg msg[] = { + { + .addr = 0x50, + .flags = 0, + .buf = data, + .len = 1 + },{ + .addr = 0x50, + .flags = I2C_M_RD, + .buf = data, + .len = length + }, + }; + if ((err = i2c_transfer(&mantis->adapter, msg, 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", + err, data[0], data[1]); + + return err; + } + msleep_interruptible(2); + + return 0; +} + +static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + int err; + + struct i2c_msg msg = { + .addr = 0x50, + .flags = 0, + .buf = data, + .len = length + }; + + if ((err = i2c_transfer(&mantis->adapter, &msg, 1)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", + err, length, data[0], data[1]); + + return err; + } + + return 0; +} + +static int get_subdevice_id(struct mantis_pci *mantis) +{ + int err; + static u8 sub_device_id[2]; + + mantis->sub_device_id = 0; + sub_device_id[0] = 0xfc; + if ((err = read_eeprom_byte(mantis, &sub_device_id[0], 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + return err; + } + mantis->sub_device_id = (sub_device_id[0] << 8) | sub_device_id[1]; + dprintk(verbose, MANTIS_ERROR, 1, "Sub Device ID=[0x%04x]", + mantis->sub_device_id); + + return 0; +} + +static int get_subvendor_id(struct mantis_pci *mantis) +{ + int err; + static u8 sub_vendor_id[2]; + + mantis->sub_vendor_id = 0; + sub_vendor_id[0] = 0xfe; + if ((err = read_eeprom_byte(mantis, &sub_vendor_id[0], 2)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + return err; + } + mantis->sub_vendor_id = (sub_vendor_id[0] << 8) | sub_vendor_id[1]; + dprintk(verbose, MANTIS_ERROR, 1, "Sub Vendor ID=[0x%04x]", + mantis->sub_vendor_id); + + return 0; +} + +static int get_mac_address(struct mantis_pci *mantis) +{ + int err; + + mantis->mac_address[0] = 0x08; + if ((err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); + + return err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]", + mantis->mac_address[0], mantis->mac_address[1], + mantis->mac_address[2], mantis->mac_address[3], + mantis->mac_address[4], mantis->mac_address[5]); + + return 0; +} + + +int mantis_core_init(struct mantis_pci *mantis) +{ + int err = 0; + + if ((err = mantis_i2c_init(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); + return err; + } + if ((err = get_mac_address(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); + return err; + } + if ((err = get_subvendor_id(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get Sub vendor ID failed"); + return err; + } + if ((err = get_subdevice_id(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "get Sub device ID failed"); + return err; + } + if ((err = mantis_dma_init(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); + return err; + } + if ((err = mantis_dvb_init(mantis)) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); + return err; + } + + return 0; +} + +int mantis_core_exit(struct mantis_pci *mantis) +{ + + mantis_dma_stop(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); + if (mantis_dma_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + if (mantis_dvb_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed"); + if (mantis_i2c_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed"); + + return 0; +} + +void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) +{ + u32 reg; + + if (value) + reg = 0x0000; + else + reg = 0xffff; + + reg = (value << bitpos); + + mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); + udelay(100); + mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); +} + + +//direction = 0 , no CI passthrough ; 1 , CI passthrough +void mantis_set_direction(struct mantis_pci *mantis, int direction) +{ + u32 reg; + + reg = mmread(0x28); + dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); + if (direction == 0x01) { //to CI + reg |= 0x04; + mmwrite(reg, 0x28); + reg &= 0xff - 0x04; + mmwrite(reg, 0x28); + } else { + reg &= 0xff - 0x04; + mmwrite(reg, 0x28); + reg |= 0x04; + mmwrite(reg, 0x28); + } +} diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h new file mode 100644 index 00000000000..31b2a756d99 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -0,0 +1,61 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_CORE_H +#define __MANTIS_CORE_H + +#include "mantis_common.h" + + +#define FE_TYPE_SAT 0 +#define FE_TYPE_CAB 1 +#define FE_TYPE_TER 2 + +#define FE_TYPE_TS204 0 +#define FE_TYPE_TS188 1 + + +struct vendorname { + __u8 *sub_vendor_name; + __u32 sub_vendor_id; +}; + +struct devicetype { + __u8 *sub_device_name; + __u32 sub_device_id; + __u8 device_type; + __u32 type_flags; +}; + + +extern int mantis_dma_init(struct mantis_pci *mantis); +extern int mantis_dma_exit(struct mantis_pci *mantis); +extern void mantis_dma_start(struct mantis_pci *mantis); +extern void mantis_dma_stop(struct mantis_pci *mantis); +extern int mantis_i2c_init(struct mantis_pci *mantis); +extern int mantis_i2c_exit(struct mantis_pci *mantis); +extern int mantis_core_init(struct mantis_pci *mantis); +extern int mantis_core_exit(struct mantis_pci *mantis); +//extern void mantis_fe_powerup(struct mantis_pci *mantis); +//extern void mantis_fe_powerdown(struct mantis_pci *mantis); +//extern void mantis_fe_reset(struct dvb_frontend *fe); +extern void mantis_set_direction(struct mantis_pci *mantis, int direction); + +#endif //__MANTIS_CORE_H diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c new file mode 100644 index 00000000000..9e3aa5ec164 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -0,0 +1,238 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include "mantis_common.h" + +#define RISC_WRITE (0x01 << 28) +#define RISC_JUMP (0x07 << 28) +#define RISC_IRQ (0x01 << 24) + +#define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) +#define RISC_FLUSH() mantis->risc_pos = 0 +#define RISC_INSTR(opcode) mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode) + +#define MANTIS_BUF_SIZE 64 * 1024 +#define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) +#define MANTIS_BLOCK_COUNT (1 << 4) +#define MANTIS_RISC_SIZE PAGE_SIZE + +int mantis_dma_exit(struct mantis_pci *mantis) +{ + if (mantis->buf_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "DMA=0x%lx cpu=0x%p size=%d", + (unsigned long) mantis->buf_dma, + mantis->buf_cpu, + MANTIS_BUF_SIZE); + + pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, + mantis->buf_cpu, mantis->buf_dma); + + mantis->buf_cpu = NULL; + } + if (mantis->risc_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "RISC=0x%lx cpu=0x%p size=%lx", + (unsigned long) mantis->risc_dma, + mantis->risc_cpu, + MANTIS_RISC_SIZE); + + pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, + mantis->risc_cpu, mantis->risc_dma); + + mantis->risc_cpu = NULL; + } + + return 0; +} + +static inline int mantis_alloc_buffers(struct mantis_pci *mantis) +{ + if (!mantis->buf_cpu) { + mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, + MANTIS_BUF_SIZE, + &mantis->buf_dma); + if (!mantis->buf_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "DMA buffer allocation failed"); + + goto err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "DMA=0x%lx cpu=0x%p size=%d", + (unsigned long) mantis->buf_dma, + mantis->buf_cpu, MANTIS_BUF_SIZE); + } + if (!mantis->risc_cpu) { + mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, + MANTIS_RISC_SIZE, + &mantis->risc_dma); + + if (!mantis->risc_cpu) { + dprintk(verbose, MANTIS_ERROR, 1, + "RISC program allocation failed"); + + mantis_dma_exit(mantis); + + goto err; + } + dprintk(verbose, MANTIS_ERROR, 1, + "RISC=0x%lx cpu=0x%p size=%lx", + (unsigned long) mantis->risc_dma, + mantis->risc_cpu, MANTIS_RISC_SIZE); + } + + return 0; +err: + dprintk(verbose, MANTIS_ERROR, 1, "Out of memory (?) ....."); + return -ENOMEM; +} + +static inline int mantis_calc_lines(struct mantis_pci *mantis) +{ + mantis->line_bytes = MANTIS_BLOCK_BYTES; + mantis->line_count = MANTIS_BLOCK_COUNT; + + while (mantis->line_bytes > 4095) { + mantis->line_bytes >>= 1; + mantis->line_count <<= 1; + } + + dprintk(verbose, MANTIS_DEBUG, 1, + "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", + MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); + + if (mantis->line_count > 255) { + dprintk(verbose, MANTIS_ERROR, 1, "Buffer size error"); + return -EINVAL; + } + + return 0; +} + +int mantis_dma_init(struct mantis_pci *mantis) +{ + int err = 0; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DMA init"); + if (mantis_alloc_buffers(mantis) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Error allocating DMA buffer"); + + // Stop RISC Engine +// mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); + mmwrite(0, MANTIS_DMA_CTL); + + goto err; + } + if ((err = mantis_calc_lines(mantis)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis calc lines failed"); + + goto err; + } + + return 0; +err: + return err; +} + + + +static inline void mantis_risc_program(struct mantis_pci *mantis) +{ + u32 buf_pos = 0; + u32 line; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis create RISC program"); + RISC_FLUSH(); + + dprintk(verbose, MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", + mantis->line_count, mantis->line_bytes); + + for (line = 0; line < mantis->line_count; line++) { + dprintk(verbose, MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); + if (!(buf_pos % MANTIS_BLOCK_BYTES)) { + RISC_INSTR(RISC_WRITE | + RISC_IRQ | + RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) + + (MANTIS_BLOCK_COUNT - 1)) % + MANTIS_BLOCK_COUNT) | + mantis->line_bytes); + } else { + RISC_INSTR(RISC_WRITE | mantis->line_bytes); + } + RISC_INSTR(mantis->buf_dma + buf_pos); + buf_pos += mantis->line_bytes; + } + RISC_INSTR(RISC_JUMP); + RISC_INSTR(mantis->risc_dma); +} + +void mantis_dma_start(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); + + mantis_risc_program(mantis); + mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); + mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + + mmwrite(0, MANTIS_DMA_CTL); + mantis->last_block = mantis->finished_block = 0; + + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); + + mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN + | MANTIS_RISC_EN, MANTIS_DMA_CTL); + +} + +void mantis_dma_stop(struct mantis_pci *mantis) +{ + u32 stat = 0, mask = 0; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + + mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | + MANTIS_DCAP_EN | + MANTIS_RISC_EN)), MANTIS_DMA_CTL); + + mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); + + mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | + MANTIS_INT_RISCEN), MANTIS_INT_MASK); +} + + +void mantis_dma_xfer(unsigned long data) +{ + struct mantis_pci *mantis = (struct mantis_pci *) data; + + while (mantis->last_block != mantis->finished_block) { + dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", + mantis->last_block, mantis->finished_block); + + (mantis->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); + mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; + } +} diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c new file mode 100644 index 00000000000..5830d4a7bda --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -0,0 +1,304 @@ +/* + Mantis PCI bridge driver + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "mantis_common.h" +#include "mantis_core.h" + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp2033.h" +#include "mantis_vp3030.h" + +/* Tuner power supply control */ +void mantis_fe_powerup(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power ON"); + gpio_set_bits(mantis, 0x0c, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 0x0c, 1); + msleep_interruptible(100); +} + +void mantis_fe_powerdown(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF"); + gpio_set_bits(mantis, 0x0c, 0); +} + +static int mantis_fe_reset(struct dvb_frontend *fe) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + + return 0; +} + +static int mantis_frontend_reset(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 0); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + msleep_interruptible(100); + gpio_set_bits(mantis, 13, 1); + + return 0; +} + +static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct mantis_pci *mantis = dvbdmx->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Start feed"); + if (!dvbdmx->dmx.frontend) { + dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + return -EINVAL; + } + mantis->feeds++; + dprintk(verbose, MANTIS_DEBUG, 1, + "mantis start feed, feeds=%d", + mantis->feeds); + + if (mantis->feeds == 1) { + dprintk(verbose, MANTIS_DEBUG, 1, "mantis start feed & dma"); + printk("mantis start feed & dma\n"); + mantis_dma_start(mantis); + } + + return mantis->feeds; +} + +static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) +{ + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct mantis_pci *mantis = dvbdmx->priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); + if (!dvbdmx->dmx.frontend) { + dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + return -EINVAL; + } + mantis->feeds--; + if (mantis->feeds == 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "mantis stop feed and dma"); + printk("mantis stop feed and dma\n"); + mantis_dma_stop(mantis); + } + return 0; +} + +int __devinit mantis_dvb_init(struct mantis_pci *mantis) +{ + int result; + + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); + if (dvb_register_adapter(&mantis->dvb_adapter, + "Mantis dvb adapter", THIS_MODULE, + &mantis->pdev->dev) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); + return -ENODEV; + } + mantis->dvb_adapter.priv = mantis; + mantis->demux.dmx.capabilities = DMX_TS_FILTERING | + DMX_SECTION_FILTERING | + DMX_MEMORY_BASED_FILTERING; + + mantis->demux.priv = mantis; + mantis->demux.filternum = 256; + mantis->demux.feednum = 256; + mantis->demux.start_feed = mantis_dvb_start_feed; + mantis->demux.stop_feed = mantis_dvb_stop_feed; + mantis->demux.write_to_decoder = NULL; + mantis->ts_size = 1; //188 + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); + if ((result = dvb_dmx_init(&mantis->demux)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err0; + } + mantis->dmxdev.filternum = 256; + mantis->dmxdev.demux = &mantis->demux.dmx; + mantis->dmxdev.capabilities = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmxdev_init"); + if ((result = dvb_dmxdev_init(&mantis->dmxdev, + &mantis->dvb_adapter)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmxdev_init failed, ERROR=%d", result); + goto err1; + } + mantis->fe_hw.source = DMX_FRONTEND_0; + if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, + &mantis->fe_hw)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err2; + } + mantis->fe_mem.source = DMX_MEMORY_FE; + if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, + &mantis->fe_mem)) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err3; + } + if ((result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, + &mantis->fe_hw)) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, + "dvb_dmx_init failed, ERROR=%d", result); + + goto err4; + } + dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); + tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); + mantis_frontend_init(mantis); + return 0; + + /* Error conditions .. */ +err4: + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); +err3: + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); +err2: + dvb_dmxdev_release(&mantis->dmxdev); +err1: + dvb_dmx_release(&mantis->demux); +err0: + dvb_unregister_adapter(&mantis->dvb_adapter); + + return result; +} + +#define MANTIS_VP_1027_DVB_S 0x0013 +#define MANTIS_VP_1033_DVB_S 0x0016 +#define MANTIS_VP_1034_DVB_S 0x0014 +#define MANTIS_VP_1040_DVB_S2 +#define MANTIS_VP_1041_DVB_S2 +#define MANTIS_VP_2033_DVB_C 0x0008 +#define MANTIS_VP_3024_DVB_T 0x0009 +#define MANTIS_VP_3030_DVB_T 0x0024 + +int __devinit mantis_frontend_init(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); + mantis_fe_powerup(mantis); + mantis_frontend_reset(mantis); + dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->sub_device_id); + switch (mantis->sub_device_id) { + case MANTIS_VP_1033_DVB_S: // VP-1033 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + mantis->fe = stv0299_attach(&lgtdqcs001f_config, + &mantis->adapter); + + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-S STV0299 frontend attach success"); + } + break; + case MANTIS_VP_1034_DVB_S: // VP-1034 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter); + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_config.demod_address); + + } + break; + case MANTIS_VP_2033_DVB_C: // VP-2033 + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = cu1216_attach(&philips_cu1216_config, &mantis->adapter); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend @ 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + + } + break; + default: + dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", + mantis->sub_device_id); + + return -ENODEV; + } + if (mantis->fe == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); + return -ENODEV; + } else { + if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { + dprintk(verbose, MANTIS_ERROR, 1, + "ERROR: Frontend registration failed"); + + if (mantis->fe->ops.release) + mantis->fe->ops.release(mantis->fe); + + mantis->fe = NULL; + return -ENODEV; + } + } + + return 0; +} + +int __devexit mantis_dvb_exit(struct mantis_pci *mantis) +{ + tasklet_kill(&mantis->tasklet); + dvb_net_release(&mantis->dvbnet); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + dvb_dmxdev_release(&mantis->dmxdev); + dvb_dmx_release(&mantis->demux); + + if (mantis->fe) + dvb_unregister_frontend(mantis->fe); + dprintk(verbose, MANTIS_DEBUG, 1, "dvb_unregister_adapter"); + dvb_unregister_adapter(&mantis->dvb_adapter); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c new file mode 100644 index 00000000000..cfecb344bb7 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -0,0 +1,189 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mantis_common.h" + +#define I2C_HW_B_MANTIS 0x1c + +static int mantis_ack_wait(struct mantis_pci *mantis) +{ + int rc = 0; + + if (wait_event_interruptible_timeout(mantis->i2c_wq, + mantis->mantis_int_stat & MANTIS_INT_I2CRACK, + msecs_to_jiffies(50)) == -ERESTARTSYS) + + rc = -EREMOTEIO; +/* + // Wait till we are done + while (mantis->mantis_int_stat & MANTIS_INT_I2CRACK){ + if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { + mantis->mantis_int_stat &= ~MANTIS_INT_I2CRACK; +// dprintk(verbose, MANTIS_DEBUG, 1, "SLAVE RACK 'ed .. Waiting for I2CDONE"); + break; + } + } + + if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { +// dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Int I2CDONE"); + rc = 1; + } + + mantis->mantis_int_stat &= ~MANTIS_INT_I2CDONE; +*/ + // .. + if (mantis->mantis_int_stat & MANTIS_INT_I2CRACK) + msleep_interruptible(10); + + return rc; +} + +static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) +{ + u32 rxd, i; + + dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + for (i = 0; i < msg->len; i++) { + rxd = (msg->addr << 25) | (1 << 24) + | MANTIS_I2C_RATE_3 + | MANTIS_I2C_STOP + | MANTIS_I2C_PGMODE; + + if (i == (msg->len - 1)) + rxd &= ~MANTIS_I2C_STOP; + + mmwrite(rxd, MANTIS_I2CDATA_CTL); + if (mantis_ack_wait(mantis) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + return -EIO; + } + rxd = mmread(MANTIS_I2CDATA_CTL); + msg->buf[i] = (u8)((rxd >> 8) & 0xFF); + dprintk(verbose, MANTIS_DEBUG, 1, + "Data=[0x%02x]", i, msg->buf[i]); + + msleep_interruptible(2); + } + + return 0; +} + +static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg) +{ + int i; + u32 txd = 0; + + dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + for (i = 0; i < msg->len; i++) { + dprintk(verbose, MANTIS_DEBUG, 1, "Data=[0x%02x]", i, msg->buf[i]); + txd = (msg->addr << 25) | (msg->buf[i] << 8) + | MANTIS_I2C_RATE_3 + | MANTIS_I2C_STOP + | MANTIS_I2C_PGMODE; + + if (i == (msg->len - 1)) + txd &= ~MANTIS_I2C_STOP; + + mmwrite(txd, MANTIS_I2CDATA_CTL); + if (mantis_ack_wait(mantis) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + return -1; + } + udelay(500); + } + + return 0; +} + +static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + int ret = 0, i; + struct mantis_pci *mantis; + + mantis = i2c_get_adapdata(adapter); + for (i = 0; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) + ret = mantis_i2c_read(mantis, &msgs[i]); + else + ret = mantis_i2c_write(mantis, &msgs[i]); + + if (ret < 0) + return ret; + } + + return num; +} + +static u32 mantis_i2c_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm mantis_algo = { + .master_xfer = mantis_i2c_xfer, + .functionality = mantis_i2c_func, +}; + +static struct i2c_adapter mantis_i2c_adapter = { + .owner = THIS_MODULE, + .name = "Mantis I2C", + .id = I2C_HW_B_MANTIS, + .class = I2C_CLASS_TV_DIGITAL, + .algo = &mantis_algo, +}; + +int __devinit mantis_i2c_init(struct mantis_pci *mantis) +{ + u32 intstat; + + memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + i2c_set_adapdata(&mantis->adapter, mantis); + mantis->i2c_rc = i2c_add_adapter(&mantis->adapter); + if (mantis->i2c_rc < 0) + return mantis->i2c_rc; + + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); + + // Clear all interrupts + intstat = mmread(MANTIS_INT_STAT); + mmwrite(intstat, MANTIS_INT_STAT); + + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_I2CDONE, + MANTIS_INT_MASK); + + dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", + mmread(MANTIS_INT_STAT), mmread(MANTIS_INT_MASK)); + + return 0; +} + +int __devexit mantis_i2c_exit(struct mantis_pci *mantis) +{ + dprintk(verbose, MANTIS_DEBUG, 1, "Removing I2C adapter"); + return i2c_del_adapter(&mantis->adapter); +} diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h new file mode 100644 index 00000000000..1b54e09fd86 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -0,0 +1,109 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_REG_H +#define __MANTIS_REG_H + +// Interrupts +#define MANTIS_INT_STAT 0x00 +#define MANTIS_INT_MASK 0x04 + +#define MANTIS_INT_RISCSTAT (0x0f << 28) +#define MANTIS_INT_RISCEN (0x01 << 27) +#define MANTIS_INT_I2CRACK (0x01 << 26) + +//#define MANTIS_INT_GPIF (0xff << 12) + +#define MANTIS_INT_PCMCIA7 (0x01 << 19) +#define MANTIS_INT_PCMCIA6 (0x01 << 18) +#define MANTIS_INT_PCMCIA5 (0x01 << 17) +#define MANTIS_INT_PCMCIA4 (0x01 << 16) +#define MANTIS_INT_PCMCIA3 (0x01 << 15) +#define MANTIS_INT_PCMCIA2 (0x01 << 14) +#define MANTIS_INT_PCMCIA1 (0x01 << 13) +#define MANTIS_INT_PCMCIA0 (0x01 << 12) +#define MANTIS_INT_IRQ1 (0x01 << 11) +#define MANTIS_INT_IRQ0 (0x01 << 10) +#define MANTIS_INT_OCERR (0x01 << 8) +#define MANTIS_INT_PABORT (0x01 << 7) +#define MANTIS_INT_RIPERR (0x01 << 6) +#define MANTIS_INT_PPERR (0x01 << 5) +#define MANTIS_INT_FTRGT (0x01 << 3) +#define MANTIS_INT_RISCI (0x01 << 1) +#define MANTIS_INT_I2CDONE (0x01 << 0) + +// DMA +#define MANTIS_DMA_CTL 0x08 +#define MANTIS_I2C_RD (0x01 << 7) +#define MANTIS_I2C_WR (0x01 << 6) +#define MANTIS_DCAP_MODE (0x01 << 5) +#define MANTIS_FIFO_TP_4 (0x00 << 3) +#define MANTIS_FIFO_TP_8 (0x01 << 3) +#define MANTIS_FIFO_TP_16 (0x02 << 3) +#define MANTIS_FIFO_EN (0x01 << 2) +#define MANTIS_DCAP_EN (0x01 << 1) +#define MANTIS_RISC_EN (0x01 << 0) + +#define MANTIS_RISC_START 0x10 +#define MANTIS_RISC_PC 0x14 + +// I2C +#define MANTIS_I2CDATA_CTL 0x18 +#define MANTIS_I2C_RATE_1 (0x00 << 6) +#define MANTIS_I2C_RATE_2 (0x01 << 6) +#define MANTIS_I2C_RATE_3 (0x02 << 6) +#define MANTIS_I2C_RATE_4 (0x03 << 6) +#define MANTIS_I2C_STOP (0x01 << 5) +#define MANTIS_I2C_PGMODE (0x01 << 3) + +#define MANTIS_GPIF_IRQCFG 0x98 +#define MANTIS_GPIF_IRQPOL (0x01 << 8) +#define MANTIS_MASK_WRACK (0x01 << 7) +#define MANTIS_MASK_BRRDY (0x01 << 6) +#define MANTIS_MASK_OVFLW (0x01 << 5) +#define MANTIS_MASK_OTHERR (0x01 << 4) +#define MANTIS_MASK_WSTO (0x01 << 3) +#define MANTIS_MASK_EXTIRQ (0x01 << 2) +#define MANTIS_MASK_PLUGIN (0x01 << 1) +#define MANTIS_MASK_PLUGOUT (0x01 << 0) + +#define MANTIS_GPIF_STATUS 0x9c +#define MANTIS_SBUF_KILLOP (0x01 << 15) +#define MANTIS_SBUF_OPDONE (0x01 << 14) +#define MANTIS_SBUF_EMPTY (0x01 << 13) +#define MANTIS_GPIF_DETSTAT (0x01 << 9) +#define MANTIS_GPIF_INTSTAT (0x01 << 8) +#define MANTIS_GPIF_WRACK (0x01 << 7) +#define MANTIS_GPIF_BRRDY (0x01 << 6) +#define MANTIS_SBUF_OVFLW (0x01 << 5) +#define MANTIS_GPIF_OTHERR (0x01 << 4) +#define MANTIS_SBUF_WSTO (0x01 << 3) +#define MANTIS_GPIF_EXTIRQ (0x01 << 2) +#define MANTIS_CARD_PLUGIN (0x01 << 1) +#define MANTIS_CARD_PLUGOUT (0x01 << 0) + +#define MANTIS_GPIF_ADDR 0xb0 +#define MANTIS_GPIF_RDWRN (0x01 << 31) + +#define MANTIS_GPIF_DOUT 0xb4 +#define MANTIS_GPIF_DIN 0xb8 + + +#endif //__MANTIS_REG_H diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c new file mode 100644 index 00000000000..720f4fb7e92 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -0,0 +1,151 @@ +/* + Mantis VP-1033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1033.h" + +u8 lgtdqcs001f_inittab[] = { + 0x01, 0x15, + 0x02, 0x00, + 0x03, 0x00, + 0x04, 0x2a, + 0x05, 0x85, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x00, + 0x0c, 0x01, + 0x0d, 0x81, + 0x0e, 0x44, + 0x0f, 0x94, + 0x10, 0x3c, + 0x11, 0x84, + 0x12, 0xb9, + 0x13, 0xb5, + 0x14, 0x4f, + 0x15, 0xc9, + 0x16, 0x80, + 0x17, 0x36, + 0x18, 0xfb, + 0x19, 0xcf, + 0x1a, 0xbc, + 0x1c, 0x2b, + 0x1d, 0x27, + 0x1e, 0x00, + 0x1f, 0x0b, + 0x20, 0xa1, + 0x21, 0x60, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, + 0x29, 0x28, + 0x2a, 0x14, + 0x2b, 0x0f, + 0x2c, 0x09, + 0x2d, 0x05, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x13, + 0xff, 0xff, +}; + +struct stv0299_config lgtdqcs001f_config = { + .demod_address = 0x68, + .inittab = lgtdqcs001f_inittab, + .mclk = 88000000UL, +// .invert = 0, + .invert = 1, +// .enhanced_tuning = 0, + .skip_reinit = 0, + .lock_output = STV0229_LOCKOUTPUT_0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = lgtdqcs001f_set_symbol_rate, +// .pll_set = lgtdqcs001f_pll_set, +}; + +int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + u32 div; + + struct mantis_pci *mantis = fe->dvb->priv; + + struct i2c_msg msg = { + .addr = 0x61, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + div = params->frequency / 250; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x83; + buf[3] = 0xc0; + + if (params->frequency < 1531000) + buf[3] |= 0x04; + else + buf[3] &= ~0x04; + if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Write: I2C Transfer failed"); + return -EIO; + } + msleep_interruptible(100); + + return 0; +} + +int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, + u32 srate, u32 ratio) +{ + u8 aclk = 0; + u8 bclk = 0; + + if (srate < 1500000) { + aclk = 0xb7; + bclk = 0x47; + } else if (srate < 3000000) { + aclk = 0xb7; + bclk = 0x4b; + } else if (srate < 7000000) { + aclk = 0xb7; + bclk = 0x4f; + } else if (srate < 14000000) { + aclk = 0xb7; + bclk = 0x53; + } else if (srate < 30000000) { + aclk = 0xb6; + bclk = 0x53; + } else if (srate < 45000000) { + aclk = 0xb4; + bclk = 0x51; + } + stv0299_writereg (fe, 0x13, aclk); + stv0299_writereg (fe, 0x14, bclk); + + stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h new file mode 100644 index 00000000000..d50f09233ff --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -0,0 +1,35 @@ +/* + Mantis VP-1033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1033_H +#define __MANTIS_VP1033_H + +#include "stv0299.h" +#include "dvb_frontend.h" + +extern struct stv0299_config lgtdqcs001f_config; + +extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + +extern int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio); + + +#endif // __MANTIS_VP1033_H diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c new file mode 100644 index 00000000000..b85ac29691d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -0,0 +1,52 @@ +/* + Mantis VP-1034 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1034.h" + +struct mb86a16_config vp1034_config = { + .demod_address = 0x08, + .set_voltage = vp1034_set_voltage, +}; + +int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + switch (voltage) { + case SEC_VOLTAGE_13: + mmwrite((mmread(MANTIS_GPIF_ADDR)) | voltage, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + break; + case SEC_VOLTAGE_18: + mmwrite((mmread(MANTIS_GPIF_ADDR)) & voltage, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + break; + case SEC_VOLTAGE_OFF: + dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); + break; + default: + dprintk(verbose, MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + return -EINVAL; + } + mmwrite(0x00, MANTIS_GPIF_DOUT); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h new file mode 100644 index 00000000000..2324dada09d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -0,0 +1,30 @@ +/* + Mantis VP-1034 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1034_H +#define __MANTIS_VP1034_H + +#include "mb86a16.h" +#include "dvb_frontend.h" + +extern struct mb86a16_config vp1034_config; +extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); + +#endif // __MANTIS_VP1034_H diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c new file mode 100644 index 00000000000..bca9ebaf39d --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -0,0 +1,73 @@ +/* + Mantis VP-2033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp2033.h" + +struct tda10021_state { + struct i2c_adapter *i2c; + struct dvb_frontend_ops ops; + /* configuration settings */ + const struct tda10021_config *config; + struct dvb_frontend frontend; + + u8 pwm; + u8 reg0; +}; + +struct cu1216_config philips_cu1216_config = { + .demod_address = 0x18 >> 1, + .pll_set = philips_cu1216_tuner_set, +// .fe_reset = mantis_fe_reset, +}; + +int philips_cu1216_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ +// struct tda10021_state *state = fe->demodulator_priv; + struct mantis_pci *mantis = fe->dvb->priv; + + u8 buf[4]; + + struct i2c_msg msg = { + .addr = 0xc0 >> 1, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + +#define TUNER_MUL 62500 + + u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0x86; + buf[3] = (params->frequency < 150000000 ? 0xA1 : + params->frequency < 445000000 ? 0x92 : 0x34); + +// if (i2c_transfer(state->i2c, &msg, 1) < 0) { + if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { + printk("%s tuner not ack!\n", __FUNCTION__); + return -EIO; + } + msleep(100); + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h new file mode 100644 index 00000000000..29baba18096 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -0,0 +1,33 @@ +/* + Mantis VP-2033 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP2033_H +#define __MANTIS_VP2033_H + +#include "cu1216.h" +#include "dvb_frontend.h" + +extern struct cu1216_config philips_cu1216_config; + +extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params); + + +#endif // __MANTIS_VP2033_H diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c new file mode 100644 index 00000000000..f44f226ce9a --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -0,0 +1,53 @@ +/* + Mantis VP-3030 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp3030.h" + +struct zl10353_config mantis_vp3030_config = { + .demod_address = 0x0f, +}; + +int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u8 buf[4]; + int rc; + struct mantis_pci *mantis = fe->dvb->priv; + + struct i2c_msg tuner_msg = { + .addr = 0x60, + .flags = 0, + .buf = buf, + .len = sizeof (buf) + }; + + if ((params->frequency < 950000) || (params->frequency > 2150000)) + return -EINVAL; + rc = i2c_transfer(&mantis->adapter, &tuner_msg, 1); + if (rc != 1) { + printk("%s: I2C Transfer returned [%d]\n", __func__, rc); + return -EIO; + } + msleep_interruptible(1); + printk("%s: Send params to tuner ok!!!\n", __func__); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h new file mode 100644 index 00000000000..f8e72cce7e6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -0,0 +1,30 @@ +/* + Mantis VP-3030 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP3030_H +#define __MANTIS_VP3030_H + +#include "zl10353.h" +#include "dvb-pll.h" +#include "dvb_frontend.h" + +extern struct zl10353_config mantis_vp3030_config; + +#endif // __MANTIS_VP3030_H -- cgit v1.2.3 From a890cce595c86013ca1fba644c25c01b86149b23 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 21:58:38 -0300 Subject: V4L/DVB (13700): [MB86A16] Need a bit of settling time Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 6a78a0c7403..e8fa90801d7 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -243,11 +243,16 @@ static int initial_set(struct mb86a16_state *state) { if (stlp_set(state, 5, 7)) goto err; + + udelay(100); if (afcex_data_set(state, 0, 0)) goto err; + + udelay(100); if (afcofs_data_set(state, 0, 0)) goto err; + udelay(100); if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0) goto err; if (mb86a16_write(state, 0x2f, 0x21) < 0) @@ -1149,11 +1154,12 @@ static int mb86a16_set_fe(struct mb86a16_state *state) v, R, swp_ofs, &fOSC, &afcex_freq, &AFCEX_L, &AFCEX_H); + udelay(100); if (rf_val_set(state, fOSC, state->srate, R) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "rf val set error"); return -1; } - + udelay(100); if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error"); return -1; -- cgit v1.2.3 From b05c90de08b582172b8f63dd751ac0a1aee421e9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 21:59:20 -0300 Subject: V4L/DVB (13701): [MB86A16] Reduce Carrier Recovery range to 3Mhz Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index e8fa90801d7..47c0d5739dd 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1036,8 +1036,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate); - fcp = 5000; // (carrier recovery [kHz]) -// fcp = 3000; + fcp = 3000; swp_ofs = state->srate / 4; for (i = 0; i < 60; i++) -- cgit v1.2.3 From e15c7ccd31faa0618478ad78e11423891919a87e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:00:50 -0300 Subject: V4L/DVB (13702): [MB86A16] need to wait a bit more than the computed time for a Factor of safety Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 47c0d5739dd..ad03b110f73 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -417,7 +417,8 @@ static int signal_det(struct mb86a16_state *state, int ret ; int smrtd ; int wait_sym ; - int wait_t ; + + u32 wait_t; unsigned char S[3] ; int i ; @@ -1429,6 +1430,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; wait_t = 7 + (2097152 + state->srate / 2) / state->srate; } + wait_t *= 2; /* FOS */ S2T_set(state, S2T); S45T_set(state, S4T, S5T); Vi_set(state, ETH, VIA); -- cgit v1.2.3 From 776c3ebe9678f86b9b0e72d541208bb39f9551c6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:01:39 -0300 Subject: V4L/DVB (13703): [MB86A16] Fix wrong message printed out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index ad03b110f73..82b12714461 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1475,7 +1475,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) SEQ_set(state, 1); } } else { - dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); SEQ_set(state, 1); } } -- cgit v1.2.3 From 071e3060a5f482e5948608d55e28bc7f5dd759cd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:02:19 -0300 Subject: V4L/DVB (13704): [MB86A16] FIX: Don't loop again, if we have SYNC Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 82b12714461..361e4762346 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1487,6 +1487,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) if (sync) { dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); freqerr_chk(state, state->frequency, state->srate, 1); + break; } } -- cgit v1.2.3 From bd1fcac0148fb4a44395227edb0ff8ee31e09de1 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:06:15 -0300 Subject: V4L/DVB (13705): [Mantis] FIX: Do not return IRQ_HANDLED in the unlikely case Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 328 ++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_pci.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c new file mode 100644 index 00000000000..68ff1b2a0b3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -0,0 +1,328 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "mantis_common.h" +#include "mantis_core.h" + +#include +#include +#include +#include + +unsigned int verbose = 1; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +unsigned int devs; + +#define PCI_VENDOR_ID_MANTIS 0x1822 +#define PCI_DEVICE_ID_MANTIS_R11 0x4e35 +#define DRIVER_NAME "Mantis" + +static struct pci_device_id mantis_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MANTIS, PCI_DEVICE_ID_MANTIS_R11) }, + { 0 }, +}; + +MODULE_DEVICE_TABLE(pci, mantis_pci_table); + +static irqreturn_t mantis_pci_irq(int irq, void *dev_id) +{ + int i = 0, interrupts = 0; + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + struct mantis_pci *mantis; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + + if (!(stat & mask)) { + dprintk(verbose, MANTIS_DEBUG, 1, "Not ours !"); + return IRQ_NONE; + } + mmwrite(lstat, MANTIS_INT_STAT); + interrupts = hweight32(stat); + dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]=%d [", stat, mask, interrupts); + + while (lstat) { + if (lstat & MANTIS_INT_RISCEN) { + dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); + lstat &= ~MANTIS_INT_RISCEN; + + } else if (lstat & MANTIS_INT_I2CRACK) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + wake_up(&mantis->i2c_wq); + lstat &= ~MANTIS_INT_I2CRACK; + + } else if (lstat & MANTIS_INT_PCMCIA7) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); + lstat &= ~MANTIS_INT_PCMCIA7; + + } else if (lstat & MANTIS_INT_PCMCIA6) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-06 *"); + lstat &= ~MANTIS_INT_PCMCIA6; + + } else if (lstat & MANTIS_INT_PCMCIA5) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-05 *"); + lstat &= ~MANTIS_INT_PCMCIA5; + + } else if (lstat & MANTIS_INT_PCMCIA4) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-04 *"); + lstat &= ~MANTIS_INT_PCMCIA4; + + } else if (lstat & MANTIS_INT_PCMCIA3) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-03 *"); + lstat &= ~MANTIS_INT_PCMCIA3; + + } else if (lstat & MANTIS_INT_PCMCIA2) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-02 *"); + lstat &= ~MANTIS_INT_PCMCIA2; + + } else if (lstat & MANTIS_INT_PCMCIA1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-01 *"); + lstat &= ~MANTIS_INT_PCMCIA1; + + } else if (lstat & MANTIS_INT_PCMCIA0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-00 *"); + lstat &= ~MANTIS_INT_PCMCIA0; + + } else if (lstat & MANTIS_INT_IRQ0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + lstat &= ~MANTIS_INT_IRQ0; + + } else if (lstat & MANTIS_INT_IRQ1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + lstat &= ~MANTIS_INT_IRQ1; + + } else if (lstat & MANTIS_INT_OCERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); + lstat &= ~MANTIS_INT_OCERR; + + } else if (lstat & MANTIS_INT_PABORT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); + lstat &= ~MANTIS_INT_PABORT; + + } else if (lstat & MANTIS_INT_RIPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); + lstat &= ~MANTIS_INT_RIPERR; + + } else if (lstat & MANTIS_INT_PPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); + lstat &= ~MANTIS_INT_PPERR; + + } else if (lstat & MANTIS_INT_FTRGT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); + lstat &= ~MANTIS_INT_FTRGT; + + } else if (lstat & MANTIS_INT_RISCI) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + lstat &= ~MANTIS_INT_RISCI; + + } else if (lstat & MANTIS_INT_I2CDONE) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + lstat &= ~MANTIS_INT_I2CDONE; + } else { + dprintk(verbose, MANTIS_DEBUG, 0, + "* Unknown [%04x/%04x] *", stat, mask); + break; + } + i++; + if (i > interrupts) { + dprintk(verbose, MANTIS_ERROR, 1, "going Loopy ! -- BREAK --"); + break; + } + } + dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); + + return IRQ_HANDLED; +} + + +static int __devinit mantis_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *mantis_pci_table) +{ + u8 revision, latency; + struct mantis_pci *mantis; + int ret = 0; + + devs++; + + mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk("%s: Out of memory\n", __func__); + ret = -ENOMEM; + goto err; + } + memset(mantis, 0, sizeof (struct mantis_pci)); + mantis->num = devs; + if (pci_enable_device(pdev)) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); + ret = -ENODEV; + goto err; + } + mantis->mantis_addr = pci_resource_start(pdev, 0); + if (!request_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0), DRIVER_NAME)) { + ret = -ENODEV; + goto err0; + } + + if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); + ret = -ENODEV; + goto err1; + } + + // Clear and disable all interrupts at startup + // to avoid lockup situations + mmwrite(0x00, MANTIS_INT_MASK); + if (request_irq(pdev->irq, mantis_pci_irq, IRQF_SHARED | IRQF_DISABLED, + DRIVER_NAME, mantis) < 0) { + + dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); + ret = -ENODEV; + goto err2; + } + pci_set_master(pdev); + pci_set_drvdata(pdev, mantis); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + mantis->latency = latency; + mantis->revision = revision; + mantis->pdev = pdev; + init_waitqueue_head(&mantis->i2c_wq); + + // CAM bypass + //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); + dprintk(verbose, MANTIS_INFO, 1, "gpif status: %04x irqcfg: %04x", mmread(0x9c), mmread(0x98)); + if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted + msleep_interruptible(1); + if ((mmread(0x9c) & 0x200) != 0) + mmwrite(((mmread(0x98) | 0x01) & ~0x02), 0x98); + else + mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); + + } else { + mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); + } + mantis_set_direction(mantis, 0); + + // default latency if none specified + if (!latency) + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); + dprintk(verbose, MANTIS_ERROR, 0, "Mantis Rev %d, ", + mantis->revision); + + dprintk(verbose, MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + pdev->irq, mantis->latency, + mantis->mantis_addr, mantis->mantis_mmio); + + // No more PCI specific stuff ! + if (mantis_core_init(mantis) < 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Mantis core init failed"); + ret = -ENODEV; + goto err2; + } + + return 0; + + // Error conditions .. +err2: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: IO Unmap"); + if (mantis->mantis_mmio) + iounmap(mantis->mantis_mmio); +err1: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: Release regions"); + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + pci_disable_device(pdev); +err0: + dprintk(verbose, MANTIS_DEBUG, 1, "Err: Free"); + kfree(mantis); +err: + dprintk(verbose, MANTIS_DEBUG, 1, "Err:"); + return ret; +} + +static void __devexit mantis_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis == NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "Aeio, Mantis NULL ptr"); + return; + } + mantis_core_exit(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "Removing -->Mantis irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p", + pdev->irq, mantis->latency, mantis->mantis_addr, + mantis->mantis_mmio); + + free_irq(pdev->irq, mantis); + pci_release_regions(pdev); + if (mantis_dma_exit(mantis) < 0) + dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + + pci_set_drvdata(pdev, NULL); + pci_disable_device(pdev); + kfree(mantis); +} + +static struct pci_driver mantis_pci_driver = { + .name = DRIVER_NAME, + .id_table = mantis_pci_table, + .probe = mantis_pci_probe, + .remove = mantis_pci_remove, +}; + +static int __devinit mantis_pci_init(void) +{ + return pci_register_driver(&mantis_pci_driver); +} + +static void __devexit mantis_pci_exit(void) +{ + pci_unregister_driver(&mantis_pci_driver); +} + +module_init(mantis_pci_init); +module_exit(mantis_pci_exit); + +MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From df0cca174b4d85ea041509a13e5e68b377758bf1 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:07:24 -0300 Subject: V4L/DVB (13706): [MB86A16] Overhaul * better ISR handling * I2C fixes * better handling of configurations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 14 ++- drivers/media/dvb/mantis/mantis_core.c | 95 +++++++++-------- drivers/media/dvb/mantis/mantis_dvb.c | 13 +-- drivers/media/dvb/mantis/mantis_i2c.c | 68 ++++++------- drivers/media/dvb/mantis/mantis_pci.c | 170 ++++++++++++------------------- drivers/media/dvb/mantis/mantis_vp1033.c | 8 ++ drivers/media/dvb/mantis/mantis_vp1033.h | 6 +- drivers/media/dvb/mantis/mantis_vp1034.c | 8 ++ drivers/media/dvb/mantis/mantis_vp1034.h | 7 +- drivers/media/dvb/mantis/mantis_vp2033.c | 20 ++-- drivers/media/dvb/mantis/mantis_vp2033.h | 6 +- drivers/media/dvb/mantis/mantis_vp3030.c | 10 +- drivers/media/dvb/mantis/mantis_vp3030.h | 8 +- 13 files changed, 215 insertions(+), 218 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index ba360f88496..60a7457b2b9 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -65,10 +65,19 @@ #define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) +struct mantis_hwconfig { + char *model_name; + char *dev_type; +}; + + struct mantis_pci { /* PCI stuff */ u16 vendor_id; u16 device_id; + u16 subsystem_vendor; + u16 subsystem_device; + u8 latency; struct pci_dev *pdev; @@ -110,7 +119,7 @@ struct mantis_pci { u8 feeds; - struct mantis_config *config; + struct mantis_hwconfig *hwconfig; u32 mantis_int_stat; u32 mantis_int_mask; @@ -121,7 +130,8 @@ struct mantis_pci { u32 sub_device_id; /* A12 A13 A14 */ - int gpio_status;}; + int gpio_status; +}; extern unsigned int verbose; extern unsigned int devs; diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 11122775245..1012959499a 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -20,7 +20,10 @@ #include "mantis_common.h" #include "mantis_core.h" - +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp2033.h" +#include "mantis_vp3030.h" static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) { @@ -45,7 +48,7 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return err; } - msleep_interruptible(2); +// msleep_interruptible(2); return 0; } @@ -72,41 +75,6 @@ static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } -static int get_subdevice_id(struct mantis_pci *mantis) -{ - int err; - static u8 sub_device_id[2]; - - mantis->sub_device_id = 0; - sub_device_id[0] = 0xfc; - if ((err = read_eeprom_byte(mantis, &sub_device_id[0], 2)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); - return err; - } - mantis->sub_device_id = (sub_device_id[0] << 8) | sub_device_id[1]; - dprintk(verbose, MANTIS_ERROR, 1, "Sub Device ID=[0x%04x]", - mantis->sub_device_id); - - return 0; -} - -static int get_subvendor_id(struct mantis_pci *mantis) -{ - int err; - static u8 sub_vendor_id[2]; - - mantis->sub_vendor_id = 0; - sub_vendor_id[0] = 0xfe; - if ((err = read_eeprom_byte(mantis, &sub_vendor_id[0], 2)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); - return err; - } - mantis->sub_vendor_id = (sub_vendor_id[0] << 8) | sub_vendor_id[1]; - dprintk(verbose, MANTIS_ERROR, 1, "Sub Vendor ID=[0x%04x]", - mantis->sub_vendor_id); - - return 0; -} static int get_mac_address(struct mantis_pci *mantis) { @@ -118,8 +86,8 @@ static int get_mac_address(struct mantis_pci *mantis) return err; } - dprintk(verbose, MANTIS_ERROR, 1, - "MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]", + dprintk(verbose, MANTIS_ERROR, 0, + " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", mantis->mac_address[0], mantis->mac_address[1], mantis->mac_address[2], mantis->mac_address[3], mantis->mac_address[4], mantis->mac_address[5]); @@ -127,11 +95,51 @@ static int get_mac_address(struct mantis_pci *mantis) return 0; } +#define MANTIS_MODEL_UNKNOWN "UNKNOWN" +#define MANTIS_DEV_UNKNOWN "UNKNOWN" + +struct mantis_hwconfig unknown_device = { + .model_name = MANTIS_MODEL_UNKNOWN, + .dev_type = MANTIS_DEV_UNKNOWN, +}; + +static void mantis_load_config(struct mantis_pci *mantis) +{ + switch (mantis->subsystem_device) { + case MANTIS_VP_1033_DVB_S: // VP-1033 + mantis->hwconfig = &vp1033_mantis_config; + break; + case MANTIS_VP_1034_DVB_S: // VP-1034 + mantis->hwconfig = &vp1034_mantis_config; + break; + case MANTIS_VP_2033_DVB_C: // VP-2033 + mantis->hwconfig = &vp2033_mantis_config; + break; + case MANTIS_VP_3030_DVB_T: // VP-3030 + mantis->hwconfig = &vp3030_mantis_config; + break; + default: + mantis->hwconfig = &unknown_device; + break; + } +} int mantis_core_init(struct mantis_pci *mantis) { int err = 0; + mantis_load_config(mantis); + dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", + mantis->hwconfig->model_name, mantis->hwconfig->dev_type, + mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn)); + dprintk(verbose, MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", + mantis->revision, + mantis->subsystem_vendor, mantis->subsystem_device); + dprintk(verbose, MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + mantis->pdev->irq, mantis->latency, + mantis->mantis_addr, mantis->mantis_mmio); + if ((err = mantis_i2c_init(mantis)) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); return err; @@ -140,14 +148,6 @@ int mantis_core_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); return err; } - if ((err = get_subvendor_id(mantis)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "get Sub vendor ID failed"); - return err; - } - if ((err = get_subdevice_id(mantis)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "get Sub device ID failed"); - return err; - } if ((err = mantis_dma_init(mantis)) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); return err; @@ -162,7 +162,6 @@ int mantis_core_init(struct mantis_pci *mantis) int mantis_core_exit(struct mantis_pci *mantis) { - mantis_dma_stop(mantis); dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); if (mantis_dma_exit(mantis) < 0) diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 5830d4a7bda..319bb8bef4e 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -206,22 +206,13 @@ err0: return result; } -#define MANTIS_VP_1027_DVB_S 0x0013 -#define MANTIS_VP_1033_DVB_S 0x0016 -#define MANTIS_VP_1034_DVB_S 0x0014 -#define MANTIS_VP_1040_DVB_S2 -#define MANTIS_VP_1041_DVB_S2 -#define MANTIS_VP_2033_DVB_C 0x0008 -#define MANTIS_VP_3024_DVB_T 0x0009 -#define MANTIS_VP_3030_DVB_T 0x0024 - int __devinit mantis_frontend_init(struct mantis_pci *mantis) { dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); mantis_fe_powerup(mantis); mantis_frontend_reset(mantis); - dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->sub_device_id); - switch (mantis->sub_device_id) { + dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->subsystem_device); + switch (mantis->subsystem_device) { case MANTIS_VP_1033_DVB_S: // VP-1033 dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); mantis->fe = stv0299_attach(&lgtdqcs001f_config, diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index cfecb344bb7..8b90a2af687 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -33,32 +33,27 @@ static int mantis_ack_wait(struct mantis_pci *mantis) { int rc = 0; + u32 timeout = 0; if (wait_event_interruptible_timeout(mantis->i2c_wq, - mantis->mantis_int_stat & MANTIS_INT_I2CRACK, - msecs_to_jiffies(50)) == -ERESTARTSYS) + mantis->mantis_int_stat & MANTIS_INT_I2CDONE, + msecs_to_jiffies(50)) == -ERESTARTSYS) { + dprintk(verbose, MANTIS_DEBUG, 1, "I2C Transfer failed, Master !I2CDONE"); rc = -EREMOTEIO; -/* - // Wait till we are done - while (mantis->mantis_int_stat & MANTIS_INT_I2CRACK){ - if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { - mantis->mantis_int_stat &= ~MANTIS_INT_I2CRACK; -// dprintk(verbose, MANTIS_DEBUG, 1, "SLAVE RACK 'ed .. Waiting for I2CDONE"); + } + while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { + dprintk(verbose, MANTIS_DEBUG, 1, "Waiting for Slave RACK"); + mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); + msleep(5); + timeout++; + if (timeout > 500) { + dprintk(verbose, MANTIS_ERROR, 1, "Slave RACK Fail !"); + rc = -EREMOTEIO; break; } } - - if (mantis->mantis_int_stat & MANTIS_INT_I2CDONE) { -// dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Int I2CDONE"); - rc = 1; - } - - mantis->mantis_int_stat &= ~MANTIS_INT_I2CDONE; -*/ - // .. - if (mantis->mantis_int_stat & MANTIS_INT_I2CRACK) - msleep_interruptible(10); + udelay(350); return rc; } @@ -67,7 +62,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i; - dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { rxd = (msg->addr << 25) | (1 << 24) | MANTIS_I2C_RATE_3 @@ -77,18 +72,17 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) if (i == (msg->len - 1)) rxd &= ~MANTIS_I2C_STOP; + mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(rxd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) < 0) { + if (mantis_ack_wait(mantis) != 0) { dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); - return -EIO; + return -EREMOTEIO; } rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); - dprintk(verbose, MANTIS_DEBUG, 1, - "Data=[0x%02x]", i, msg->buf[i]); - - msleep_interruptible(2); + dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); } + dprintk(verbose, MANTIS_INFO, 0, "]\n"); return 0; } @@ -98,9 +92,9 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg int i; u32 txd = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Address=[0x%02x]", msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { - dprintk(verbose, MANTIS_DEBUG, 1, "Data=[0x%02x]", i, msg->buf[i]); + dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); txd = (msg->addr << 25) | (msg->buf[i] << 8) | MANTIS_I2C_RATE_3 | MANTIS_I2C_STOP @@ -109,13 +103,14 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg if (i == (msg->len - 1)) txd &= ~MANTIS_I2C_STOP; + mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(txd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) < 0) { + if (mantis_ack_wait(mantis) != 0) { dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); - return -1; + return -EREMOTEIO; } - udelay(500); } + dprintk(verbose, MANTIS_INFO, 0, "]\n"); return 0; } @@ -159,7 +154,7 @@ static struct i2c_adapter mantis_i2c_adapter = { int __devinit mantis_i2c_init(struct mantis_pci *mantis) { - u32 intstat; + u32 intstat, intmask; memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); i2c_set_adapdata(&mantis->adapter, mantis); @@ -169,15 +164,12 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); - // Clear all interrupts intstat = mmread(MANTIS_INT_STAT); + intmask = mmread(MANTIS_INT_MASK); mmwrite(intstat, MANTIS_INT_STAT); + mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); - mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_I2CDONE, - MANTIS_INT_MASK); - - dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", - mmread(MANTIS_INT_STAT), mmread(MANTIS_INT_MASK)); + dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", intstat, intmask); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 68ff1b2a0b3..0bc25d2778f 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -52,7 +52,6 @@ MODULE_DEVICE_TABLE(pci, mantis_pci_table); static irqreturn_t mantis_pci_irq(int irq, void *dev_id) { - int i = 0, interrupts = 0; u32 stat = 0, mask = 0, lstat = 0, mstat = 0; struct mantis_pci *mantis; @@ -64,109 +63,67 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) stat = mmread(MANTIS_INT_STAT); mask = mmread(MANTIS_INT_MASK); mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; - - if (!(stat & mask)) { - dprintk(verbose, MANTIS_DEBUG, 1, "Not ours !"); + if (!(stat & mask)) return IRQ_NONE; + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); + } + if (stat & MANTIS_INT_I2CRACK) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); +// wake_up(&mantis->i2c_wq); + } + if (stat & MANTIS_INT_PCMCIA7) { + dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); } - mmwrite(lstat, MANTIS_INT_STAT); - interrupts = hweight32(stat); - dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]=%d [", stat, mask, interrupts); - - while (lstat) { - if (lstat & MANTIS_INT_RISCEN) { - dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); - lstat &= ~MANTIS_INT_RISCEN; - - } else if (lstat & MANTIS_INT_I2CRACK) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); - mantis->mantis_int_stat = stat; - mantis->mantis_int_mask = mask; - wake_up(&mantis->i2c_wq); - lstat &= ~MANTIS_INT_I2CRACK; - - } else if (lstat & MANTIS_INT_PCMCIA7) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); - lstat &= ~MANTIS_INT_PCMCIA7; - - } else if (lstat & MANTIS_INT_PCMCIA6) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-06 *"); - lstat &= ~MANTIS_INT_PCMCIA6; - - } else if (lstat & MANTIS_INT_PCMCIA5) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-05 *"); - lstat &= ~MANTIS_INT_PCMCIA5; - - } else if (lstat & MANTIS_INT_PCMCIA4) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-04 *"); - lstat &= ~MANTIS_INT_PCMCIA4; - - } else if (lstat & MANTIS_INT_PCMCIA3) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-03 *"); - lstat &= ~MANTIS_INT_PCMCIA3; - - } else if (lstat & MANTIS_INT_PCMCIA2) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-02 *"); - lstat &= ~MANTIS_INT_PCMCIA2; - - } else if (lstat & MANTIS_INT_PCMCIA1) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-01 *"); - lstat &= ~MANTIS_INT_PCMCIA1; - - } else if (lstat & MANTIS_INT_PCMCIA0) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-00 *"); - lstat &= ~MANTIS_INT_PCMCIA0; - - } else if (lstat & MANTIS_INT_IRQ0) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); - lstat &= ~MANTIS_INT_IRQ0; - - } else if (lstat & MANTIS_INT_IRQ1) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); - lstat &= ~MANTIS_INT_IRQ1; - - } else if (lstat & MANTIS_INT_OCERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); - lstat &= ~MANTIS_INT_OCERR; - - } else if (lstat & MANTIS_INT_PABORT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); - lstat &= ~MANTIS_INT_PABORT; - - } else if (lstat & MANTIS_INT_RIPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); - lstat &= ~MANTIS_INT_RIPERR; - - } else if (lstat & MANTIS_INT_PPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); - lstat &= ~MANTIS_INT_PPERR; - - } else if (lstat & MANTIS_INT_FTRGT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); - lstat &= ~MANTIS_INT_FTRGT; - - } else if (lstat & MANTIS_INT_RISCI) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); - mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; - tasklet_schedule(&mantis->tasklet); - lstat &= ~MANTIS_INT_RISCI; - - } else if (lstat & MANTIS_INT_I2CDONE) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); - mantis->mantis_int_stat = stat; - mantis->mantis_int_mask = mask; - lstat &= ~MANTIS_INT_I2CDONE; - } else { - dprintk(verbose, MANTIS_DEBUG, 0, - "* Unknown [%04x/%04x] *", stat, mask); - break; - } - i++; - if (i > interrupts) { - dprintk(verbose, MANTIS_ERROR, 1, "going Loopy ! -- BREAK --"); - break; - } + if (stat & MANTIS_INT_PPERR) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); } + if (stat & MANTIS_INT_FTRGT) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(verbose, MANTIS_DEBUG, 0, "* Unknown [%04x] *", stat); + dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); return IRQ_HANDLED; @@ -180,8 +137,6 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, struct mantis_pci *mantis; int ret = 0; - devs++; - mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); if (mantis == NULL) { printk("%s: Out of memory\n", __func__); @@ -190,6 +145,8 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, } memset(mantis, 0, sizeof (struct mantis_pci)); mantis->num = devs; + devs++; + if (pci_enable_device(pdev)) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); ret = -ENODEV; @@ -225,11 +182,13 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, mantis->latency = latency; mantis->revision = revision; mantis->pdev = pdev; + mantis->subsystem_vendor = pdev->subsystem_vendor; + mantis->subsystem_device = pdev->subsystem_device; init_waitqueue_head(&mantis->i2c_wq); // CAM bypass //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); - dprintk(verbose, MANTIS_INFO, 1, "gpif status: %04x irqcfg: %04x", mmread(0x9c), mmread(0x98)); + dprintk(verbose, MANTIS_INFO, 0, "\ngpif status: %04x irqcfg: %04x\n", mmread(0x9c), mmread(0x98)); if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted msleep_interruptible(1); if ((mmread(0x9c) & 0x200) != 0) @@ -242,11 +201,8 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, } mantis_set_direction(mantis, 0); - // default latency if none specified if (!latency) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); - dprintk(verbose, MANTIS_ERROR, 0, "Mantis Rev %d, ", - mantis->revision); dprintk(verbose, MANTIS_ERROR, 0, "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 720f4fb7e92..07fcc45b7f6 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -81,6 +81,14 @@ struct stv0299_config lgtdqcs001f_config = { // .pll_set = lgtdqcs001f_pll_set, }; +#define MANTIS_MODEL_NAME "VP-1033" +#define MANTIS_DEV_TYPE "DVB-S/DSS" + +struct mantis_hwconfig vp1033_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, +}; + int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h index d50f09233ff..e24570659d5 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -21,10 +21,14 @@ #ifndef __MANTIS_VP1033_H #define __MANTIS_VP1033_H -#include "stv0299.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "stv0299.h" + +#define MANTIS_VP_1033_DVB_S 0x0016 extern struct stv0299_config lgtdqcs001f_config; +extern struct mantis_hwconfig vp1033_mantis_config; extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index b85ac29691d..c9c94791162 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -26,6 +26,14 @@ struct mb86a16_config vp1034_config = { .set_voltage = vp1034_set_voltage, }; +#define MANTIS_MODEL_NAME "VP-1034" +#define MANTIS_DEV_TYPE "DVB-S/DSS" + +struct mantis_hwconfig vp1034_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, +}; + int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct mantis_pci *mantis = fe->dvb->priv; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h index 2324dada09d..21948573b08 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -21,9 +21,14 @@ #ifndef __MANTIS_VP1034_H #define __MANTIS_VP1034_H -#include "mb86a16.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "mb86a16.h" + + +#define MANTIS_VP_1034_DVB_S 0x0014 +extern struct mantis_hwconfig vp1034_mantis_config; extern struct mb86a16_config vp1034_config; extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index bca9ebaf39d..e9895976912 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -32,9 +32,17 @@ struct tda10021_state { u8 reg0; }; +#define MANTIS_MODEL_NAME "VP-2033" +#define MANTIS_DEV_TYPE "DVB-C" + +struct mantis_hwconfig vp2033_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, +}; + struct cu1216_config philips_cu1216_config = { - .demod_address = 0x18 >> 1, - .pll_set = philips_cu1216_tuner_set, + .demod_address = 0x18 >> 1, + .pll_set = philips_cu1216_tuner_set, // .fe_reset = mantis_fe_reset, }; @@ -47,10 +55,10 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, u8 buf[4]; struct i2c_msg msg = { - .addr = 0xc0 >> 1, - .flags = 0, - .buf = buf, - .len = sizeof (buf) + .addr = 0xc0 >> 1, + .flags = 0, + .buf = buf, + .len = sizeof (buf) }; #define TUNER_MUL 62500 diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index 29baba18096..513c491942c 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -21,10 +21,14 @@ #ifndef __MANTIS_VP2033_H #define __MANTIS_VP2033_H -#include "cu1216.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "cu1216.h" + +#define MANTIS_VP_2033_DVB_C 0x0008 extern struct cu1216_config philips_cu1216_config; +extern struct mantis_hwconfig vp2033_mantis_config; extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index f44f226ce9a..8043e5d9218 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -22,7 +22,15 @@ #include "mantis_vp3030.h" struct zl10353_config mantis_vp3030_config = { - .demod_address = 0x0f, + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3030" +#define MANTIS_DEV_TYPE "DVB-T" + +struct mantis_hwconfig vp3030_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, }; int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h index f8e72cce7e6..acc50a48e18 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -21,10 +21,14 @@ #ifndef __MANTIS_VP3030_H #define __MANTIS_VP3030_H -#include "zl10353.h" -#include "dvb-pll.h" #include "dvb_frontend.h" +#include "mantis_common.h" +#include "dvb-pll.h" +#include "zl10353.h" + +#define MANTIS_VP_3030_DVB_T 0x0024 extern struct zl10353_config mantis_vp3030_config; +extern struct mantis_hwconfig vp3030_mantis_config; #endif // __MANTIS_VP3030_H -- cgit v1.2.3 From 55172773c57221c7c81e445d04f811f2f0478c3e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:09:53 -0300 Subject: V4L/DVB (13707): [Mantis] Whitespace cleanup Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 60a7457b2b9..d39cbe0f241 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -83,7 +83,7 @@ struct mantis_pci { struct pci_dev *pdev; unsigned long mantis_addr; - volatile void __iomem *mantis_mmio; + volatile void __iomem *mantis_mmio; u8 irq; u8 revision; @@ -121,8 +121,8 @@ struct mantis_pci { struct mantis_hwconfig *hwconfig; - u32 mantis_int_stat; - u32 mantis_int_mask; + u32 mantis_int_stat; + u32 mantis_int_mask; /* board specific */ u8 mac_address[8]; -- cgit v1.2.3 From da7365f46607207c8166167ba497e3cb3e02270d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 2 Dec 2009 22:11:00 -0300 Subject: V4L/DVB (13708): [Mantis] Remove some dead code Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 2 -- drivers/media/dvb/mantis/mantis_pci.c | 1 - drivers/media/dvb/mantis/mantis_vp2033.c | 14 +------------- 3 files changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 1012959499a..d159ad6fc32 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -48,7 +48,6 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return err; } -// msleep_interruptible(2); return 0; } @@ -75,7 +74,6 @@ static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } - static int get_mac_address(struct mantis_pci *mantis) { int err; diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 0bc25d2778f..402f866e12d 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -74,7 +74,6 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_I2CRACK) { dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); -// wake_up(&mantis->i2c_wq); } if (stat & MANTIS_INT_PCMCIA7) { dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index e9895976912..853b558b928 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -21,17 +21,6 @@ #include "mantis_common.h" #include "mantis_vp2033.h" -struct tda10021_state { - struct i2c_adapter *i2c; - struct dvb_frontend_ops ops; - /* configuration settings */ - const struct tda10021_config *config; - struct dvb_frontend frontend; - - u8 pwm; - u8 reg0; -}; - #define MANTIS_MODEL_NAME "VP-2033" #define MANTIS_DEV_TYPE "DVB-C" @@ -49,7 +38,6 @@ struct cu1216_config philips_cu1216_config = { int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { -// struct tda10021_state *state = fe->demodulator_priv; struct mantis_pci *mantis = fe->dvb->priv; u8 buf[4]; @@ -71,11 +59,11 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, buf[3] = (params->frequency < 150000000 ? 0xA1 : params->frequency < 445000000 ? 0x92 : 0x34); -// if (i2c_transfer(state->i2c, &msg, 1) < 0) { if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { printk("%s tuner not ack!\n", __FUNCTION__); return -EIO; } msleep(100); + return 0; } -- cgit v1.2.3 From 715d341c59d2563940ae07b12f949555ccbe3efb Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:37:51 -0300 Subject: V4L/DVB (13709): [Mantis/VP-1034] Switch 13/18v for the VP-1034 properly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 10 +++++++--- drivers/media/dvb/mantis/mantis_vp1034.c | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 8b90a2af687..53c5f88227b 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -39,7 +39,7 @@ static int mantis_ack_wait(struct mantis_pci *mantis) mantis->mantis_int_stat & MANTIS_INT_I2CDONE, msecs_to_jiffies(50)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_DEBUG, 1, "I2C Transfer failed, Master !I2CDONE"); + dprintk(verbose, MANTIS_DEBUG, 1, "Master !I2CDONE"); rc = -EREMOTEIO; } while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { @@ -62,7 +62,9 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + __func__, msg->addr); + for (i = 0; i < msg->len; i++) { rxd = (msg->addr << 25) | (1 << 24) | MANTIS_I2C_RATE_3 @@ -92,7 +94,9 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg int i; u32 txd = 0; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); + dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + __func__, msg->addr); + for (i = 0; i < msg->len; i++) { dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); txd = (msg->addr << 25) | (msg->buf[i] << 8) diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index c9c94791162..f6766d0793d 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -40,12 +40,14 @@ int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) switch (voltage) { case SEC_VOLTAGE_13: - mmwrite((mmread(MANTIS_GPIF_ADDR)) | voltage, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + gpio_set_bits(mantis, 13, 1); + gpio_set_bits(mantis, 14, 0); break; case SEC_VOLTAGE_18: - mmwrite((mmread(MANTIS_GPIF_ADDR)) & voltage, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + gpio_set_bits(mantis, 13, 1); + gpio_set_bits(mantis, 14, 1); break; case SEC_VOLTAGE_OFF: dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); -- cgit v1.2.3 From 01a8c3eebb3c83df337f88332756f16154cecc0f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:38:33 -0300 Subject: V4L/DVB (13710): [Mantis] FIX: Use swfilter (188/204) accordingly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 4 +++- drivers/media/dvb/mantis/mantis_dma.c | 2 -- drivers/media/dvb/mantis/mantis_vp1033.c | 1 + drivers/media/dvb/mantis/mantis_vp1034.c | 1 + drivers/media/dvb/mantis/mantis_vp2033.c | 1 + drivers/media/dvb/mantis/mantis_vp3030.c | 1 + 6 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index d39cbe0f241..197393e700f 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -64,13 +64,15 @@ #define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) #define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) +#define MANTIS_TS_188 0 +#define MANTIS_TS_204 1 struct mantis_hwconfig { char *model_name; char *dev_type; + u32 ts_size; }; - struct mantis_pci { /* PCI stuff */ u16 vendor_id; diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 9e3aa5ec164..b8fd1c7cd29 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -154,8 +154,6 @@ err: return err; } - - static inline void mantis_risc_program(struct mantis_pci *mantis) { u32 buf_pos = 0; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 07fcc45b7f6..daf02c12d29 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -87,6 +87,7 @@ struct stv0299_config lgtdqcs001f_config = { struct mantis_hwconfig vp1033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, }; int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index f6766d0793d..a2fe9d42d1e 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -32,6 +32,7 @@ struct mb86a16_config vp1034_config = { struct mantis_hwconfig vp1034_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, }; int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 853b558b928..15772fe5828 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -27,6 +27,7 @@ struct mantis_hwconfig vp2033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, }; struct cu1216_config philips_cu1216_config = { diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 8043e5d9218..cab092ce230 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -31,6 +31,7 @@ struct zl10353_config mantis_vp3030_config = { struct mantis_hwconfig vp3030_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, }; int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, -- cgit v1.2.3 From e4deee04ffda9b44f367a40dbad8306ab88cb321 Mon Sep 17 00:00:00 2001 From: Marko Ristola Date: Thu, 3 Dec 2009 05:39:22 -0300 Subject: V4L/DVB (13711): [Mantis] FIX: Do nor toggle GPIF status Signed-off-by: Marko Ristola Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index b8fd1c7cd29..e207870fb45 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,8 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); - mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); +// mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); mantis->last_block = mantis->finished_block = 0; @@ -210,6 +211,8 @@ void mantis_dma_stop(struct mantis_pci *mantis) mask = mmread(MANTIS_INT_MASK); dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_RDWRN))), MANTIS_GPIF_ADDR); + mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | MANTIS_DCAP_EN | MANTIS_RISC_EN)), MANTIS_DMA_CTL); -- cgit v1.2.3 From e2f67e4fb931b975058b3bd48eaac43780c92c88 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:42:10 -0300 Subject: V4L/DVB (13712): [Mantis] Add locking for concurrent access Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_i2c.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 197393e700f..e354e7678a5 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "dvbdev.h" #include "dvb_demux.h" @@ -109,6 +110,7 @@ struct mantis_pci { struct i2c_adapter adapter; int i2c_rc; wait_queue_head_t i2c_wq; + struct mutex i2c_lock; /* DVB stuff */ struct dvb_adapter dvb_adapter; diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 53c5f88227b..39fabe572c2 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -125,6 +125,7 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in struct mantis_pci *mantis; mantis = i2c_get_adapdata(adapter); + mutex_lock(&mantis->i2c_lock); for (i = 0; i < num; i++) { if (msgs[i].flags & I2C_M_RD) ret = mantis_i2c_read(mantis, &msgs[i]); @@ -134,6 +135,7 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in if (ret < 0) return ret; } + mutex_unlock(&mantis->i2c_lock); return num; } @@ -160,6 +162,7 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) { u32 intstat, intmask; + mutex_init(&mantis->i2c_lock); memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); i2c_set_adapdata(&mantis->adapter, mantis); mantis->i2c_rc = i2c_add_adapter(&mantis->adapter); -- cgit v1.2.3 From 1fa1f107852484157c5453cc6c4a60c792f06c35 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Thu, 3 Dec 2009 05:44:00 -0300 Subject: V4L/DVB (13713): [MB86A16] Fix: Initialize SNR/STATUS Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 361e4762346..4f8ef2e2ecd 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -595,6 +595,7 @@ static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct mb86a16_state *state = fe->demodulator_priv; + *status = 0; if (state->signal & 0x02) *status |= FE_HAS_VITERBI; if (state->signal & 0x01) @@ -1693,6 +1694,7 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) int low_tide = 2, high_tide = 30, q_level; u8 cn; + *snr = 0; if (mb86a16_read(state, 0x26, &cn) != 2) { dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); return -EREMOTEIO; -- cgit v1.2.3 From 33c79630dd9fb7658dbb885a22e3a8127b16a38a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:44:38 -0300 Subject: V4L/DVB (13714): [MB86A16] FIX/Code simplification: use hwconfig->ts_size instead of ts_size thanks to Marko Ristola for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 1 - drivers/media/dvb/mantis/mantis_dma.c | 4 ++-- drivers/media/dvb/mantis/mantis_dvb.c | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index e354e7678a5..d4865e4f346 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -92,7 +92,6 @@ struct mantis_pci { u8 revision; unsigned int num; - u16 ts_size; /* RISC Core */ u32 finished_block; diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index e207870fb45..ea23a89c03f 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,6 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); -// mmwrite(MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); @@ -227,12 +226,13 @@ void mantis_dma_stop(struct mantis_pci *mantis) void mantis_dma_xfer(unsigned long data) { struct mantis_pci *mantis = (struct mantis_pci *) data; + struct mantis_hwconfig *config = mantis->hwconfig; while (mantis->last_block != mantis->finished_block) { dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", mantis->last_block, mantis->finished_block); - (mantis->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; } diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 319bb8bef4e..7fe8541b1c5 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -142,7 +142,6 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) mantis->demux.start_feed = mantis_dvb_start_feed; mantis->demux.stop_feed = mantis_dvb_stop_feed; mantis->demux.write_to_decoder = NULL; - mantis->ts_size = 1; //188 dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); if ((result = dvb_dmx_init(&mantis->demux)) < 0) { dprintk(verbose, MANTIS_ERROR, 1, -- cgit v1.2.3 From 8154bad4c488c1a23fb504a6e751d71a39733b76 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:46:06 -0300 Subject: V4L/DVB (13715): [Mantis] Kernel I2C changes: use PCI parent device Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_i2c.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index d4865e4f346..34d2389f312 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -83,7 +83,7 @@ struct mantis_pci { u8 latency; - struct pci_dev *pdev; + struct pci_dev *pdev; unsigned long mantis_addr; volatile void __iomem *mantis_mmio; diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 39fabe572c2..005df1e90a1 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -161,11 +161,15 @@ static struct i2c_adapter mantis_i2c_adapter = { int __devinit mantis_i2c_init(struct mantis_pci *mantis) { u32 intstat, intmask; + struct i2c_adapter *i2c_adapter = &mantis->adapter; + struct pci_dev *pdev = mantis->pdev; mutex_init(&mantis->i2c_lock); - memcpy(&mantis->adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); - i2c_set_adapdata(&mantis->adapter, mantis); - mantis->i2c_rc = i2c_add_adapter(&mantis->adapter); + memcpy(i2c_adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + i2c_set_adapdata(i2c_adapter, mantis); + + i2c_adapter->dev.parent = &pdev->dev; + mantis->i2c_rc = i2c_add_adapter(i2c_adapter); if (mantis->i2c_rc < 0) return mantis->i2c_rc; -- cgit v1.2.3 From 417036844823313901d7f7d7b963f215cc3b0641 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 3 Dec 2009 05:47:11 -0300 Subject: V4L/DVB (13716): [Mantis] Bug: incorrect byte swap You know, the worst endianness errors are not the cases where people forget to byte-swap, but the cases where they either byte-swap with the wrong size, or byte-swap when they shouldn't have done so at all. Those ones defeat the casual reader of the code. Signed-off-by: David Woodhouse Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index ea23a89c03f..f685992f7d0 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -189,7 +189,7 @@ void mantis_dma_start(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); mantis_risc_program(mantis); - mmwrite(cpu_to_le32(mantis->risc_dma), MANTIS_RISC_START); + mmwrite(mantis->risc_dma, MANTIS_RISC_START); mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); -- cgit v1.2.3 From 77557abef0de3f1f1e8f563db6df8710a9e930fe Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Thu, 3 Dec 2009 05:48:13 -0300 Subject: V4L/DVB (13717): [MB86A16] Statistics Updates * Demodulator status check made reliable * Code simplification for Viterbi Sync check, makes acquisition more reliable * Implement a BER monitor * Implement a Signal strength monitor * Implement a "simple" UCB monitor, no real UCB monitor Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 142 ++++++++++++++++++++++++++++------ 1 file changed, 117 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 4f8ef2e2ecd..eddb35baaf0 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -36,7 +36,6 @@ struct mb86a16_state { struct i2c_adapter *i2c_adap; const struct mb86a16_config *config; struct dvb_frontend frontend; - u8 signal; // tuning parameters int frequency; @@ -593,17 +592,39 @@ err: static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status) { + u8 stat, stat2; struct mb86a16_state *state = fe->demodulator_priv; *status = 0; - if (state->signal & 0x02) - *status |= FE_HAS_VITERBI; - if (state->signal & 0x01) + + if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2) + goto err; + if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2) + goto err; + if ((stat > 25) && (stat2 > 25)) + *status |= FE_HAS_SIGNAL; + if ((stat > 45) && (stat2 > 45)) + *status |= FE_HAS_CARRIER; + + if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2) + goto err; + + if (stat & 0x01) *status |= FE_HAS_SYNC; - if (state->signal & 0x03) + if (stat & 0x01) + *status |= FE_HAS_VITERBI; + + if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2) + goto err; + + if ((stat & 0x0f) && (*status & FE_HAS_VITERBI)) *status |= FE_HAS_LOCK; return 0; + +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; } static int sync_chk(struct mb86a16_state *state, @@ -1439,10 +1460,6 @@ static int mb86a16_set_fe(struct mb86a16_state *state) msleep_interruptible(wait_t); sync = sync_chk(state, &VIRM); dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); - if (mb86a16_read(state, 0x0d, &state->signal) != 2) { - dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); - return -EREMOTEIO; - } if (VIRM) { if (VIRM == 4) { // 5/6 if (SIG1 > 110) @@ -1459,22 +1476,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state) iq_vt_set(state, 1); FEC_srst(state); } - if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; - else - wait_t = (1572864 + state->srate / 2) / state->srate; - - msleep_interruptible(wait_t); - SEQ_set(state, 1); - } else { // 1/2, 2/3, 3/4, 7/8 - if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; - else - wait_t = (1572864 + state->srate / 2) / state->srate; - - msleep_interruptible(wait_t); - SEQ_set(state, 1); } + // 1/2, 2/3, 3/4, 7/8 + if (SIG1 > 110) + wait_t = ( 786432 + state->srate / 2) / state->srate; + else + wait_t = (1572864 + state->srate / 2) / state->srate; + msleep_interruptible(wait_t); + SEQ_set(state, 1); } else { dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); SEQ_set(state, 1); @@ -1648,12 +1657,85 @@ static int mb86a16_sleep(struct dvb_frontend *fe) static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber) { + u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst; + u32 timer; + + struct mb86a16_state *state = fe->demodulator_priv; + + *ber = 0; + if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2) + goto err; + if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2) + goto err; + /* BER monitor invalid when BER_EN = 0 */ + if (ber_mon & 0x04) { + /* coarse, fast calculation */ + *ber = ber_tab & 0x1f; + dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber); + if (ber_mon & 0x01) { + /* + * BER_SEL = 1, The monitored BER is the estimated + * value with a Reed-Solomon decoder error amount at + * the deinterleaver output. + * monitored BER is expressed as a 20 bit output in total + */ + ber_rst = ber_mon >> 3; + *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; + if (ber_rst == 0) + timer = 12500000; + if (ber_rst == 1) + timer = 25000000; + if (ber_rst == 2) + timer = 50000000; + if (ber_rst == 3) + timer = 100000000; + + *ber /= timer; + dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); + } else { + /* + * BER_SEL = 0, The monitored BER is the estimated + * value with a Viterbi decoder error amount at the + * QPSK demodulator output. + * monitored BER is expressed as a 24 bit output in total + */ + ber_tim = ber_mon >> 1; + *ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb; + if (ber_tim == 0) + timer = 16; + if (ber_tim == 1) + timer = 24; + + *ber /= 2 ^ timer; + dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber); + } + } return 0; +err: + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; } static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { + u8 agcm = 0; + struct mb86a16_state *state = fe->demodulator_priv; + *strength = 0; + if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + + *strength = ((0xff - agcm) * 100) / 256; + dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength); + *strength = (0xffff - 0xff) + agcm; return 0; } @@ -1708,12 +1790,22 @@ static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr) } q_level = (*snr * 100) / (high_tide - low_tide); dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level); + *snr = (0xffff - 0xff) + *snr; return 0; } static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) { + u8 dist; + struct mb86a16_state *state = fe->demodulator_priv; + + if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) { + dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); + return -EREMOTEIO; + } + *ucblocks = dist; + return 0; } @@ -1723,7 +1815,7 @@ static struct dvb_frontend_ops mb86a16_ops = { .type = FE_QPSK, .frequency_min = 950000, .frequency_max = 2150000, - .frequency_stepsize = 125, + .frequency_stepsize = 3000, .frequency_tolerance = 0, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, -- cgit v1.2.3 From f8e26cdec5ac25ae8d73e278e21033292de5430b Mon Sep 17 00:00:00 2001 From: Marko Ristola Date: Fri, 4 Dec 2009 04:35:35 -0300 Subject: V4L/DVB (13718): [Mantis] Use gpio_set_bits to turn OFF the bits as well Signed-off-by: Marko Ristola Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index d159ad6fc32..16d693eeb29 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -172,25 +172,23 @@ int mantis_core_exit(struct mantis_pci *mantis) return 0; } +// Turn the given bit on or off. void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { - u32 reg; + u32 currVal, newVal; + + currVal = mmread(MANTIS_GPIF_ADDR); if (value) - reg = 0x0000; + newVal = currVal | (1 << bitpos); else - reg = 0xffff; - - reg = (value << bitpos); + newVal = currVal & (~(1 << bitpos)); - mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); + mmwrite(newVal, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); udelay(100); - mmwrite(mmread(MANTIS_GPIF_ADDR) | reg, MANTIS_GPIF_ADDR); - mmwrite(0x00, MANTIS_GPIF_DOUT); } - //direction = 0 , no CI passthrough ; 1 , CI passthrough void mantis_set_direction(struct mantis_pci *mantis, int direction) { -- cgit v1.2.3 From 2687d832fe0141015e2391f3755d9499e6efb83e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:39:14 -0300 Subject: V4L/DVB (13719): [Mantis/VP-2033] Initial test switch to the tda10021, from the cu1216 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 2 +- drivers/media/dvb/mantis/mantis_vp2033.c | 80 +++++++++++++++++++++++--------- drivers/media/dvb/mantis/mantis_vp2033.h | 8 ++-- 3 files changed, 63 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 7fe8541b1c5..f2556950d18 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -239,7 +239,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) break; case MANTIS_VP_2033_DVB_C: // VP-2033 dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = cu1216_attach(&philips_cu1216_config, &mantis->adapter); + mantis->fe = tda10021_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); if (mantis->fe) { mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; dprintk(verbose, MANTIS_ERROR, 1, diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 15772fe5828..4664d295921 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -27,44 +27,80 @@ struct mantis_hwconfig vp2033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_188, + .ts_size = MANTIS_TS_204, }; -struct cu1216_config philips_cu1216_config = { - .demod_address = 0x18 >> 1, - .pll_set = philips_cu1216_tuner_set, -// .fe_reset = mantis_fe_reset, +struct tda1002x_config philips_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, }; -int philips_cu1216_tuner_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) +u8 read_pwm(struct mantis_pci *mantis) { - struct mantis_pci *mantis = fe->dvb->priv; + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { + {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, + {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + }; - u8 buf[4]; + if ((i2c_transfer(&mantis->adapter, msg, 2) != 2) + || (pwm == 0xff)) + pwm = 0x48; - struct i2c_msg msg = { - .addr = 0xc0 >> 1, - .flags = 0, - .buf = buf, - .len = sizeof (buf) - }; + return pwm; +} + +int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct mantis_pci *mantis = fe->dvb->priv; + + u8 buf[6]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + int i; +#define CU1216_IF 36125000 #define TUNER_MUL 62500 - u32 div = (params->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL; + u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; - buf[2] = 0x86; - buf[3] = (params->frequency < 150000000 ? 0xA1 : - params->frequency < 445000000 ? 0x92 : 0x34); + buf[2] = 0xce; + buf[3] = (params->frequency < 150000000 ? 0x01 : + params->frequency < 445000000 ? 0x02 : 0x04); + buf[4] = 0xde; + buf[5] = 0x20; - if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { - printk("%s tuner not ack!\n", __FUNCTION__); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) return -EIO; + + /* wait for the pll lock */ + msg.flags = I2C_M_RD; + msg.len = 1; + for (i = 0; i < 20; i++) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(&mantis->adapter, &msg, 1) == 1 && (buf[0] & 0x40)) + break; + + msleep(10); } - msleep(100); + + /* switch the charge pump to the lower current */ + msg.flags = 0; + msg.len = 2; + msg.buf = &buf[2]; + buf[2] &= ~0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) + return -EIO; return 0; } diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index 513c491942c..fcf8b85be94 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -23,15 +23,15 @@ #include "dvb_frontend.h" #include "mantis_common.h" -#include "cu1216.h" +#include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 -extern struct cu1216_config philips_cu1216_config; +extern struct tda1002x_config philips_cu1216_config; extern struct mantis_hwconfig vp2033_mantis_config; -extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params); +extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); +extern u8 read_pwm(struct mantis_pci *mantis); #endif // __MANTIS_VP2033_H -- cgit v1.2.3 From 51d20db8bb9c5a14ac2320664289f13bd52625c6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:39:48 -0300 Subject: V4L/DVB (13720): [Mantis/Terratec Cinergy C] Add support for the Terratec Cinergy C PCI Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 13 +++++++++++++ drivers/media/dvb/mantis/mantis_vp2033.h | 1 + 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 16d693eeb29..3b5fea7d8d5 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -111,6 +111,7 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp1034_mantis_config; break; case MANTIS_VP_2033_DVB_C: // VP-2033 + case TERRATEC_CINERGY_C_PCI: // Terratec Cinergy C PCI mantis->hwconfig = &vp2033_mantis_config; break; case MANTIS_VP_3030_DVB_T: // VP-3030 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index f2556950d18..e2aec0c7f02 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -251,6 +251,19 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case TERRATEC_CINERGY_C_PCI: + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = tda10023_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + } + break; default: dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", mantis->sub_device_id); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index fcf8b85be94..0a753f7f742 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -26,6 +26,7 @@ #include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 +#define TERRATEC_CINERGY_C_PCI 0x1178 extern struct tda1002x_config philips_cu1216_config; extern struct mantis_hwconfig vp2033_mantis_config; -- cgit v1.2.3 From 99d96e4e9202aa046e3e2be1813ff59c84e67608 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:40:16 -0300 Subject: V4L/DVB (13721): [Mantis] Bug! Before bailing out, Unlock Thanks to hotwings for pointing out the bug Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 005df1e90a1..45d9e6bd962 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -133,11 +133,15 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in ret = mantis_i2c_write(mantis, &msgs[i]); if (ret < 0) - return ret; + goto bail_out; } mutex_unlock(&mantis->i2c_lock); return num; + +bail_out: + mutex_unlock(&mantis->i2c_lock); + return ret; } static u32 mantis_i2c_func(struct i2c_adapter *adapter) -- cgit v1.2.3 From 5e68b0aedaa34447d86ae5cc6d071251c62bef37 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:40:50 -0300 Subject: V4L/DVB (13722): [Mantis] Revert 13560 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 - drivers/media/dvb/mantis/mantis_dvb.c | 13 ------------- drivers/media/dvb/mantis/mantis_vp2033.h | 1 - 3 files changed, 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 3b5fea7d8d5..16d693eeb29 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -111,7 +111,6 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp1034_mantis_config; break; case MANTIS_VP_2033_DVB_C: // VP-2033 - case TERRATEC_CINERGY_C_PCI: // Terratec Cinergy C PCI mantis->hwconfig = &vp2033_mantis_config; break; case MANTIS_VP_3030_DVB_T: // VP-3030 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index e2aec0c7f02..f2556950d18 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -251,19 +251,6 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; - case TERRATEC_CINERGY_C_PCI: - dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10023_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); - if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend 0x%02x", - philips_cu1216_config.demod_address); - - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-C Philips CU1216 frontend attach success"); - } - break; default: dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", mantis->sub_device_id); diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index 0a753f7f742..fcf8b85be94 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -26,7 +26,6 @@ #include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 -#define TERRATEC_CINERGY_C_PCI 0x1178 extern struct tda1002x_config philips_cu1216_config; extern struct mantis_hwconfig vp2033_mantis_config; -- cgit v1.2.3 From b2eb1312faa26703e71b7b3945c8773213e9ee49 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:42:22 -0300 Subject: V4L/DVB (13723): [Mantis/VP-2040, Terratec Cinergy C] Add support for the Cinergy C, VP-2040 clone Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 13 +++++++++--- drivers/media/dvb/mantis/mantis_core.c | 4 ++++ drivers/media/dvb/mantis/mantis_dvb.c | 16 +++++++++++++- drivers/media/dvb/mantis/mantis_vp2040.c | 36 ++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_vp2040.h | 33 +++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_vp2040.c create mode 100644 drivers/media/dvb/mantis/mantis_vp2040.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index a980ff2382b..2be21bfdd24 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,6 +1,13 @@ -mantis-objs = mantis_core.o mantis_dma.o mantis_pci.o mantis_i2c.o \ - mantis_dvb.o mantis_vp1033.o mantis_vp1034.o mantis_vp2033.o \ - mantis_vp3030.o +mantis-objs = mantis_core.o \ + mantis_dma.o \ + mantis_pci.o \ + mantis_i2c.o \ + mantis_dvb.o \ + mantis_vp1033.o \ + mantis_vp1034.o \ + mantis_vp2033.o \ + mantis_vp2040.o \ + mantis_vp3030.o obj-$(CONFIG_DVB_MANTIS) += mantis.o diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 16d693eeb29..96b939247b4 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -23,6 +23,7 @@ #include "mantis_vp1033.h" #include "mantis_vp1034.h" #include "mantis_vp2033.h" +#include "mantis_vp2040.h" #include "mantis_vp3030.h" static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) @@ -113,6 +114,9 @@ static void mantis_load_config(struct mantis_pci *mantis) case MANTIS_VP_2033_DVB_C: // VP-2033 mantis->hwconfig = &vp2033_mantis_config; break; + case TERRATEC_CINERGY_C_PCI: // VP-2040 clone + mantis->hwconfig = &vp2040_mantis_config; + break; case MANTIS_VP_3030_DVB_T: // VP-3030 mantis->hwconfig = &vp3030_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index f2556950d18..15012ea5796 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -28,6 +28,7 @@ #include "mantis_vp1033.h" #include "mantis_vp1034.h" #include "mantis_vp2033.h" +#include "mantis_vp2040.h" #include "mantis_vp3030.h" /* Tuner power supply control */ @@ -243,7 +244,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) if (mantis->fe) { mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend @ 0x%02x", + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", philips_cu1216_config.demod_address); dprintk(verbose, MANTIS_ERROR, 1, @@ -251,6 +252,19 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case TERRATEC_CINERGY_C_PCI: + dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); + if (mantis->fe) { + mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + philips_cu1216_config.demod_address); + + dprintk(verbose, MANTIS_ERROR, 1, + "Mantis DVB-C Philips CU1216 frontend attach success"); + } + break; default: dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", mantis->sub_device_id); diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c new file mode 100644 index 00000000000..07da73827fd --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -0,0 +1,36 @@ +/* + Mantis VP-2040 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp2040.h" + +#define MANTIS_MODEL_NAME "VP-2040" +#define MANTIS_DEV_TYPE "DVB-C" + +struct mantis_hwconfig vp2040_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, +}; + +struct tda1002x_config tda10023_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h new file mode 100644 index 00000000000..825ccbb87ad --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -0,0 +1,33 @@ +/* + Mantis VP-2040 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP2040_H +#define __MANTIS_VP2040_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "tda1002x.h" + +#define TERRATEC_CINERGY_C_PCI 0x1178 + +extern struct tda1002x_config tda10023_cu1216_config; +extern struct mantis_hwconfig vp2040_mantis_config; + +#endif //__MANTIS_VP2040_H -- cgit v1.2.3 From 873c8c25ebca50bd60e21784c4d442c4fecb8658 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:43:04 -0300 Subject: V4L/DVB (13724): [Mantis/VP-1041] Initial support for Mantis VP-1041 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_core.c | 4 + drivers/media/dvb/mantis/mantis_dvb.c | 18 ++ drivers/media/dvb/mantis/mantis_vp1041.c | 295 +++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_vp1041.h | 36 ++++ 5 files changed, 354 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_vp1041.c create mode 100644 drivers/media/dvb/mantis/mantis_vp1041.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index 2be21bfdd24..bdf3e3629ab 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -5,6 +5,7 @@ mantis-objs = mantis_core.o \ mantis_dvb.o \ mantis_vp1033.o \ mantis_vp1034.o \ + mantis_vp1041.o \ mantis_vp2033.o \ mantis_vp2040.o \ mantis_vp3030.o diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 96b939247b4..47cfb759f0b 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -22,6 +22,7 @@ #include "mantis_core.h" #include "mantis_vp1033.h" #include "mantis_vp1034.h" +#include "mantis_vp1041.h" #include "mantis_vp2033.h" #include "mantis_vp2040.h" #include "mantis_vp3030.h" @@ -111,6 +112,9 @@ static void mantis_load_config(struct mantis_pci *mantis) case MANTIS_VP_1034_DVB_S: // VP-1034 mantis->hwconfig = &vp1034_mantis_config; break; + case MANTIS_VP_1041_DVB_S2: // VP-1041 + mantis->hwconfig = &vp1041_mantis_config; + break; case MANTIS_VP_2033_DVB_C: // VP-2033 mantis->hwconfig = &vp2033_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 15012ea5796..a4750bb22b0 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -27,6 +27,7 @@ #include "dvb_frontend.h" #include "mantis_vp1033.h" #include "mantis_vp1034.h" +#include "mantis_vp1041.h" #include "mantis_vp2033.h" #include "mantis_vp2040.h" #include "mantis_vp3030.h" @@ -238,6 +239,23 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case MANTIS_VP_1041_DVB_S2: + mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", + vp1041_config.demod_address); + + if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, &mantis->adapter)) { + if (!lnbp21_attach(mantis->fe, &mantis->adapter, 0, 0)) { + printk("%s: No LNBP21 found!\n", __FUNCTION__); + mantis->fe = NULL; + } + } else { + mantis->fe = NULL; + } + } + break; case MANTIS_VP_2033_DVB_C: // VP-2033 dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); mantis->fe = tda10021_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c new file mode 100644 index 00000000000..a3279f0e4b9 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -0,0 +1,295 @@ +/* + Mantis VP-1041 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp1041.h" +#include "stb0899_reg.h" +#include "stb0899_cfg.h" +#include "stb6100_cfg.h" + +#define MANTIS_MODEL_NAME "VP-1041" +#define MANTIS_DEV_TYPE "DSS/DVB-S/DVB-S2" + +struct mantis_hwconfig vp1041_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, +}; + +static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { + +// 0x0000000b , /* SYSREG */ + { STB0899_DEV_ID , 0x30 }, + { STB0899_DISCNTRL1 , 0x32 }, + { STB0899_DISCNTRL2 , 0x80 }, + { STB0899_DISRX_ST0 , 0x04 }, + { STB0899_DISRX_ST1 , 0x00 }, + { STB0899_DISPARITY , 0x00 }, + { STB0899_DISFIFO , 0x00 }, + { STB0899_DISSTATUS , 0x20 }, + { STB0899_DISF22 , 0x99 }, + { STB0899_DISF22RX , 0xa8 }, + //SYSREG ? + { STB0899_ACRPRESC , 0x11 }, + { STB0899_ACRDIV1 , 0x0a }, + { STB0899_ACRDIV2 , 0x05 }, + { STB0899_DACR1 , 0x00 }, + { STB0899_DACR2 , 0x00 }, + { STB0899_OUTCFG , 0x00 }, + { STB0899_MODECFG , 0x00 }, + { STB0899_IRQSTATUS_3 , 0xfe }, + { STB0899_IRQSTATUS_2 , 0x03 }, + { STB0899_IRQSTATUS_1 , 0x7c }, + { STB0899_IRQSTATUS_0 , 0xf4 }, + { STB0899_IRQMSK_3 , 0xf3 }, + { STB0899_IRQMSK_2 , 0xfc }, + { STB0899_IRQMSK_1 , 0xff }, + { STB0899_IRQMSK_0 , 0xff }, + { STB0899_IRQCFG , 0x00 }, + { STB0899_I2CCFG , 0x88 }, + { STB0899_I2CRPT , 0x5c }, + { STB0899_IOPVALUE5 , 0x00 }, + { STB0899_IOPVALUE4 , 0x33 }, + { STB0899_IOPVALUE3 , 0x6d }, + { STB0899_IOPVALUE2 , 0x90 }, + { STB0899_IOPVALUE1 , 0x60 }, + { STB0899_IOPVALUE0 , 0x00 }, + { STB0899_GPIO00CFG , 0x82 }, + { STB0899_GPIO01CFG , 0x82 }, + { STB0899_GPIO02CFG , 0x82 }, + { STB0899_GPIO03CFG , 0x82 }, + { STB0899_GPIO04CFG , 0x82 }, + { STB0899_GPIO05CFG , 0x82 }, + { STB0899_GPIO06CFG , 0x82 }, + { STB0899_GPIO07CFG , 0x82 }, + { STB0899_GPIO08CFG , 0x82 }, + { STB0899_GPIO09CFG , 0x82 }, + { STB0899_GPIO10CFG , 0x82 }, + { STB0899_GPIO11CFG , 0x82 }, + { STB0899_GPIO12CFG , 0x82 }, + { STB0899_GPIO13CFG , 0x82 }, + { STB0899_GPIO14CFG , 0x82 }, + { STB0899_GPIO15CFG , 0x82 }, + { STB0899_GPIO16CFG , 0x82 }, + { STB0899_GPIO17CFG , 0x82 }, + { STB0899_GPIO18CFG , 0x82 }, + { STB0899_GPIO19CFG , 0x82 }, + { STB0899_GPIO20CFG , 0x82 }, + { STB0899_SDATCFG , 0xb8 }, + { STB0899_SCLTCFG , 0xba }, + { STB0899_AGCRFCFG , 0x1c }, /* 0x11 */ + { STB0899_GPIO22 , 0x82 }, /* AGCBB2CFG */ + { STB0899_GPIO21 , 0x91 }, /* AGCBB1CFG */ + { STB0899_DIRCLKCFG , 0x82 }, + { STB0899_CLKOUT27CFG , 0x7e }, + { STB0899_STDBYCFG , 0x82 }, + { STB0899_CS0CFG , 0x82 }, + { STB0899_CS1CFG , 0x82 }, + { STB0899_DISEQCOCFG , 0x20 }, + { STB0899_GPIO32CFG , 0x82 }, + { STB0899_GPIO33CFG , 0x82 }, + { STB0899_GPIO34CFG , 0x82 }, + { STB0899_GPIO35CFG , 0x82 }, + { STB0899_GPIO36CFG , 0x82 }, + { STB0899_GPIO37CFG , 0x82 }, + { STB0899_GPIO38CFG , 0x82 }, + { STB0899_GPIO39CFG , 0x82 }, + { STB0899_NCOARSE , 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */ + { STB0899_SYNTCTRL , 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */ + { STB0899_FILTCTRL , 0x00 }, + { STB0899_SYSCTRL , 0x01 }, + { STB0899_STOPCLK1 , 0x20 }, + { STB0899_STOPCLK2 , 0x00 }, + { STB0899_INTBUFSTATUS , 0x00 }, + { STB0899_INTBUFCTRL , 0x0a }, + { 0xffff , 0xff }, +}; + +static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { + { STB0899_DEMOD , 0x00 }, + { STB0899_RCOMPC , 0xc9 }, + { STB0899_AGC1CN , 0x41 }, + { STB0899_AGC1REF , 0x10 }, + { STB0899_RTC , 0x7a }, + { STB0899_TMGCFG , 0x4e }, + { STB0899_AGC2REF , 0x34 }, + { STB0899_TLSR , 0x84 }, + { STB0899_CFD , 0xc7 }, + { STB0899_ACLC , 0x87 }, + { STB0899_BCLC , 0x94 }, + { STB0899_EQON , 0x41 }, + { STB0899_LDT , 0xdd }, + { STB0899_LDT2 , 0xc9 }, + { STB0899_EQUALREF , 0xb4 }, + { STB0899_TMGRAMP , 0x10 }, + { STB0899_TMGTHD , 0x30 }, + { STB0899_IDCCOMP , 0xfb }, + { STB0899_QDCCOMP , 0x03 }, + { STB0899_POWERI , 0x3b }, + { STB0899_POWERQ , 0x3d }, + { STB0899_RCOMP , 0x81 }, + { STB0899_AGCIQIN , 0x80 }, + { STB0899_AGC2I1 , 0x04 }, + { STB0899_AGC2I2 , 0xf5 }, + { STB0899_TLIR , 0x25 }, + { STB0899_RTF , 0x80 }, + { STB0899_DSTATUS , 0x00 }, + { STB0899_LDI , 0xca }, + { STB0899_CFRM , 0xf1 }, + { STB0899_CFRL , 0xf3 }, + { STB0899_NIRM , 0x2a }, + { STB0899_NIRL , 0x05 }, + { STB0899_ISYMB , 0x17 }, + { STB0899_QSYMB , 0xfa }, + { STB0899_SFRH , 0x2f }, + { STB0899_SFRM , 0x68 }, + { STB0899_SFRL , 0x40 }, + { STB0899_SFRUPH , 0x2f }, + { STB0899_SFRUPM , 0x68 }, + { STB0899_SFRUPL , 0x40 }, + { STB0899_EQUAI1 , 0xfd }, + { STB0899_EQUAQ1 , 0x04 }, + { STB0899_EQUAI2 , 0x0f }, + { STB0899_EQUAQ2 , 0xff }, + { STB0899_EQUAI3 , 0xdf }, + { STB0899_EQUAQ3 , 0xfa }, + { STB0899_EQUAI4 , 0x37 }, + { STB0899_EQUAQ4 , 0x0d }, + { STB0899_EQUAI5 , 0xbd }, + { STB0899_EQUAQ5 , 0xf7 }, + { STB0899_DSTATUS2 , 0x00 }, + { STB0899_VSTATUS , 0x00 }, + { STB0899_VERROR , 0xff }, + { STB0899_IQSWAP , 0x2a }, + { STB0899_ECNT1M , 0x00 }, + { STB0899_ECNT1L , 0x00 }, + { STB0899_ECNT2M , 0x00 }, + { STB0899_ECNT2L , 0x00 }, + { STB0899_ECNT3M , 0x00 }, + { STB0899_ECNT3L , 0x00 }, + { STB0899_FECAUTO1 , 0x06 }, + { STB0899_FECM , 0x01 }, + { STB0899_VTH12 , 0xf0 }, + { STB0899_VTH23 , 0xa0 }, + { STB0899_VTH34 , 0x78 }, + { STB0899_VTH56 , 0x4e }, + { STB0899_VTH67 , 0x48 }, + { STB0899_VTH78 , 0x38 }, + { STB0899_PRVIT , 0xff }, + { STB0899_VITSYNC , 0x19 }, + { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ + { STB0899_TSULC , 0x42 }, + { STB0899_RSLLC , 0x40 }, + { STB0899_TSLPL , 0x12 }, + { STB0899_TSCFGH , 0x0c }, + { STB0899_TSCFGM , 0x00 }, + { STB0899_TSCFGL , 0x0c }, + { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */ + { STB0899_RSSYNCDEL , 0x00 }, + { STB0899_TSINHDELH , 0x02 }, + { STB0899_TSINHDELM , 0x00 }, + { STB0899_TSINHDELL , 0x00 }, + { STB0899_TSLLSTKM , 0x00 }, + { STB0899_TSLLSTKL , 0x00 }, + { STB0899_TSULSTKM , 0x00 }, + { STB0899_TSULSTKL , 0xab }, + { STB0899_PCKLENUL , 0x00 }, + { STB0899_PCKLENLL , 0xcc }, + { STB0899_RSPCKLEN , 0xcc }, + { STB0899_TSSTATUS , 0x80 }, + { STB0899_ERRCTRL1 , 0xb6 }, + { STB0899_ERRCTRL2 , 0x96 }, + { STB0899_ERRCTRL3 , 0x89 }, + { STB0899_DMONMSK1 , 0x27 }, + { STB0899_DMONMSK0 , 0x03 }, + { STB0899_DEMAPVIT , 0x5c }, + { STB0899_PLPARM , 0x1f }, + { STB0899_PDELCTRL , 0x48 }, + { STB0899_PDELCTRL2 , 0x00 }, + { STB0899_BBHCTRL1 , 0x00 }, + { STB0899_BBHCTRL2 , 0x00 }, + { STB0899_HYSTTHRESH , 0x77 }, + { STB0899_MATCSTM , 0x00 }, + { STB0899_MATCSTL , 0x00 }, + { STB0899_UPLCSTM , 0x00 }, + { STB0899_UPLCSTL , 0x00 }, + { STB0899_DFLCSTM , 0x00 }, + { STB0899_DFLCSTL , 0x00 }, + { STB0899_SYNCCST , 0x00 }, + { STB0899_SYNCDCSTM , 0x00 }, + { STB0899_SYNCDCSTL , 0x00 }, + { STB0899_ISI_ENTRY , 0x00 }, + { STB0899_ISI_BIT_EN , 0x00 }, + { STB0899_MATSTRM , 0x00 }, + { STB0899_MATSTRL , 0x00 }, + { STB0899_UPLSTRM , 0x00 }, + { STB0899_UPLSTRL , 0x00 }, + { STB0899_DFLSTRM , 0x00 }, + { STB0899_DFLSTRL , 0x00 }, + { STB0899_SYNCSTR , 0x00 }, + { STB0899_SYNCDSTRM , 0x00 }, + { STB0899_SYNCDSTRL , 0x00 }, + { STB0899_CFGPDELSTATUS1 , 0x10 }, + { STB0899_CFGPDELSTATUS2 , 0x00 }, + { STB0899_BBFERRORM , 0x00 }, + { STB0899_BBFERRORL , 0x00 }, + { STB0899_UPKTERRORM , 0x00 }, + { STB0899_UPKTERRORL , 0x00 }, + { 0xffff , 0xff }, +}; + +struct stb0899_config vp1041_config = { + .init_dev = vp1041_stb0899_s1_init_1, + .init_s2_demod = stb0899_s2_init_2, + .init_s1_demod = vp1041_stb0899_s1_init_3, + .init_s2_fec = stb0899_s2_init_4, + .init_tst = stb0899_s1_init_5, + + .demod_address = 0x68, /* 0xd0 >> 1 */ + + .xtal_freq = 27000000, + .inversion = IQ_SWAP_ON, /* 1 */ + + .esno_ave = STB0899_DVBS2_ESNO_AVE, + .esno_quant = STB0899_DVBS2_ESNO_QUANT, + .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, + .avframes_fine = STB0899_DVBS2_AVFRAMES_FINE, + .miss_threshold = STB0899_DVBS2_MISS_THRESHOLD, + .uwp_threshold_acq = STB0899_DVBS2_UWP_THRESHOLD_ACQ, + .uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK, + .uwp_threshold_sof = STB0899_DVBS2_UWP_THRESHOLD_SOF, + .sof_search_timeout = STB0899_DVBS2_SOF_SEARCH_TIMEOUT, + + .btr_nco_bits = STB0899_DVBS2_BTR_NCO_BITS, + .btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET, + .crl_nco_bits = STB0899_DVBS2_CRL_NCO_BITS, + .ldpc_max_iter = STB0899_DVBS2_LDPC_MAX_ITER, + + .tuner_get_frequency = stb6100_get_frequency, + .tuner_set_frequency = stb6100_set_frequency, + .tuner_set_bandwidth = stb6100_set_bandwidth, + .tuner_get_bandwidth = stb6100_get_bandwidth, + .tuner_set_rfsiggain = NULL, +}; + +struct stb6100_config vp1041_stb6100_config = { + .tuner_address = 0x60, + .refclock = 27000000, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h new file mode 100644 index 00000000000..53f4cb18857 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp1041.h @@ -0,0 +1,36 @@ +/* + Mantis VP-1041 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_VP1041_H +#define __MANTIS_VP1041_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "stb0899_drv.h" +#include "stb6100.h" +#include "lnbp21.h" + +#define MANTIS_VP_1041_DVB_S2 0x0031 + +extern struct mantis_hwconfig vp1041_mantis_config; +extern struct stb0899_config vp1041_config; +extern struct stb6100_config vp1041_stb6100_config; + +#endif // __MANTIS_VP1041_H -- cgit v1.2.3 From 0131258ba7a5f776627da953b4cef775568026ea Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:44:55 -0300 Subject: V4L/DVB (13725): [Mantis/VP-1041] Revert to old register initialization parameters, for now. Thanks to eso46 for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_vp1041.c | 126 +++++++++++++++---------------- 1 file changed, 63 insertions(+), 63 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index a3279f0e4b9..8854ef390e0 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -125,102 +125,102 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_DEMOD , 0x00 }, { STB0899_RCOMPC , 0xc9 }, - { STB0899_AGC1CN , 0x41 }, + { STB0899_AGC1CN , 0x01 }, { STB0899_AGC1REF , 0x10 }, - { STB0899_RTC , 0x7a }, + { STB0899_RTC , 0x23 }, { STB0899_TMGCFG , 0x4e }, { STB0899_AGC2REF , 0x34 }, { STB0899_TLSR , 0x84 }, - { STB0899_CFD , 0xc7 }, + { STB0899_CFD , 0xf7 }, { STB0899_ACLC , 0x87 }, { STB0899_BCLC , 0x94 }, { STB0899_EQON , 0x41 }, - { STB0899_LDT , 0xdd }, - { STB0899_LDT2 , 0xc9 }, + { STB0899_LDT , 0xf1 }, + { STB0899_LDT2 , 0xe3 }, { STB0899_EQUALREF , 0xb4 }, { STB0899_TMGRAMP , 0x10 }, { STB0899_TMGTHD , 0x30 }, - { STB0899_IDCCOMP , 0xfb }, - { STB0899_QDCCOMP , 0x03 }, - { STB0899_POWERI , 0x3b }, - { STB0899_POWERQ , 0x3d }, - { STB0899_RCOMP , 0x81 }, + { STB0899_IDCCOMP , 0xfd }, + { STB0899_QDCCOMP , 0xff }, + { STB0899_POWERI , 0x0c }, + { STB0899_POWERQ , 0x0f }, + { STB0899_RCOMP , 0x6c }, { STB0899_AGCIQIN , 0x80 }, - { STB0899_AGC2I1 , 0x04 }, - { STB0899_AGC2I2 , 0xf5 }, - { STB0899_TLIR , 0x25 }, - { STB0899_RTF , 0x80 }, + { STB0899_AGC2I1 , 0x06 }, + { STB0899_AGC2I2 , 0x00 }, + { STB0899_TLIR , 0x30 }, + { STB0899_RTF , 0x7f }, { STB0899_DSTATUS , 0x00 }, - { STB0899_LDI , 0xca }, - { STB0899_CFRM , 0xf1 }, - { STB0899_CFRL , 0xf3 }, - { STB0899_NIRM , 0x2a }, - { STB0899_NIRL , 0x05 }, - { STB0899_ISYMB , 0x17 }, - { STB0899_QSYMB , 0xfa }, + { STB0899_LDI , 0xbc }, + { STB0899_CFRM , 0xea }, + { STB0899_CFRL , 0x31 }, + { STB0899_NIRM , 0x2b }, + { STB0899_NIRL , 0x80 }, + { STB0899_ISYMB , 0x1d }, + { STB0899_QSYMB , 0xa6 }, { STB0899_SFRH , 0x2f }, { STB0899_SFRM , 0x68 }, { STB0899_SFRL , 0x40 }, { STB0899_SFRUPH , 0x2f }, { STB0899_SFRUPM , 0x68 }, { STB0899_SFRUPL , 0x40 }, - { STB0899_EQUAI1 , 0xfd }, - { STB0899_EQUAQ1 , 0x04 }, - { STB0899_EQUAI2 , 0x0f }, - { STB0899_EQUAQ2 , 0xff }, - { STB0899_EQUAI3 , 0xdf }, - { STB0899_EQUAQ3 , 0xfa }, - { STB0899_EQUAI4 , 0x37 }, - { STB0899_EQUAQ4 , 0x0d }, - { STB0899_EQUAI5 , 0xbd }, - { STB0899_EQUAQ5 , 0xf7 }, + { STB0899_EQUAI1 , 0x02 }, + { STB0899_EQUAQ1 , 0xff }, + { STB0899_EQUAI2 , 0x04 }, + { STB0899_EQUAQ2 , 0x05 }, + { STB0899_EQUAI3 , 0x02 }, + { STB0899_EQUAQ3 , 0xfd }, + { STB0899_EQUAI4 , 0x03 }, + { STB0899_EQUAQ4 , 0x07 }, + { STB0899_EQUAI5 , 0x08 }, + { STB0899_EQUAQ5 , 0xf5 }, { STB0899_DSTATUS2 , 0x00 }, { STB0899_VSTATUS , 0x00 }, - { STB0899_VERROR , 0xff }, + { STB0899_VERROR , 0x86 }, { STB0899_IQSWAP , 0x2a }, { STB0899_ECNT1M , 0x00 }, { STB0899_ECNT1L , 0x00 }, { STB0899_ECNT2M , 0x00 }, { STB0899_ECNT2L , 0x00 }, - { STB0899_ECNT3M , 0x00 }, - { STB0899_ECNT3L , 0x00 }, + { STB0899_ECNT3M , 0x0a }, + { STB0899_ECNT3L , 0xad }, { STB0899_FECAUTO1 , 0x06 }, { STB0899_FECM , 0x01 }, - { STB0899_VTH12 , 0xf0 }, - { STB0899_VTH23 , 0xa0 }, - { STB0899_VTH34 , 0x78 }, - { STB0899_VTH56 , 0x4e }, - { STB0899_VTH67 , 0x48 }, - { STB0899_VTH78 , 0x38 }, + { STB0899_VTH12 , 0xb0 }, + { STB0899_VTH23 , 0x7a }, + { STB0899_VTH34 , 0x58 }, + { STB0899_VTH56 , 0x38 }, + { STB0899_VTH67 , 0x34 }, + { STB0899_VTH78 , 0x24 }, { STB0899_PRVIT , 0xff }, { STB0899_VITSYNC , 0x19 }, { STB0899_RSULC , 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */ { STB0899_TSULC , 0x42 }, - { STB0899_RSLLC , 0x40 }, + { STB0899_RSLLC , 0x41 }, { STB0899_TSLPL , 0x12 }, { STB0899_TSCFGH , 0x0c }, { STB0899_TSCFGM , 0x00 }, - { STB0899_TSCFGL , 0x0c }, - { STB0899_TSOUT , 0x0d }, /* 0x0d for CAM */ + { STB0899_TSCFGL , 0x00 }, + { STB0899_TSOUT , 0x69 }, /* 0x0d for CAM */ { STB0899_RSSYNCDEL , 0x00 }, { STB0899_TSINHDELH , 0x02 }, { STB0899_TSINHDELM , 0x00 }, { STB0899_TSINHDELL , 0x00 }, - { STB0899_TSLLSTKM , 0x00 }, - { STB0899_TSLLSTKL , 0x00 }, + { STB0899_TSLLSTKM , 0x1b }, + { STB0899_TSLLSTKL , 0xb3 }, { STB0899_TSULSTKM , 0x00 }, - { STB0899_TSULSTKL , 0xab }, - { STB0899_PCKLENUL , 0x00 }, + { STB0899_TSULSTKL , 0x00 }, + { STB0899_PCKLENUL , 0xbc }, { STB0899_PCKLENLL , 0xcc }, - { STB0899_RSPCKLEN , 0xcc }, - { STB0899_TSSTATUS , 0x80 }, + { STB0899_RSPCKLEN , 0xbd }, + { STB0899_TSSTATUS , 0x90 }, { STB0899_ERRCTRL1 , 0xb6 }, - { STB0899_ERRCTRL2 , 0x96 }, - { STB0899_ERRCTRL3 , 0x89 }, + { STB0899_ERRCTRL2 , 0x95 }, + { STB0899_ERRCTRL3 , 0x8d }, { STB0899_DMONMSK1 , 0x27 }, { STB0899_DMONMSK0 , 0x03 }, { STB0899_DEMAPVIT , 0x5c }, - { STB0899_PLPARM , 0x1f }, + { STB0899_PLPARM , 0x19 }, { STB0899_PDELCTRL , 0x48 }, { STB0899_PDELCTRL2 , 0x00 }, { STB0899_BBHCTRL1 , 0x00 }, @@ -237,19 +237,19 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { STB0899_SYNCDCSTL , 0x00 }, { STB0899_ISI_ENTRY , 0x00 }, { STB0899_ISI_BIT_EN , 0x00 }, - { STB0899_MATSTRM , 0x00 }, - { STB0899_MATSTRL , 0x00 }, - { STB0899_UPLSTRM , 0x00 }, - { STB0899_UPLSTRL , 0x00 }, - { STB0899_DFLSTRM , 0x00 }, + { STB0899_MATSTRM , 0xf0 }, + { STB0899_MATSTRL , 0x02 }, + { STB0899_UPLSTRM , 0x45 }, + { STB0899_UPLSTRL , 0x60 }, + { STB0899_DFLSTRM , 0xe3 }, { STB0899_DFLSTRL , 0x00 }, - { STB0899_SYNCSTR , 0x00 }, - { STB0899_SYNCDSTRM , 0x00 }, - { STB0899_SYNCDSTRL , 0x00 }, - { STB0899_CFGPDELSTATUS1 , 0x10 }, - { STB0899_CFGPDELSTATUS2 , 0x00 }, + { STB0899_SYNCSTR , 0x47 }, + { STB0899_SYNCDSTRM , 0x05 }, + { STB0899_SYNCDSTRL , 0x18 }, + { STB0899_CFGPDELSTATUS1 , 0x19 }, + { STB0899_CFGPDELSTATUS2 , 0x2b }, { STB0899_BBFERRORM , 0x00 }, - { STB0899_BBFERRORL , 0x00 }, + { STB0899_BBFERRORL , 0x01 }, { STB0899_UPKTERRORM , 0x00 }, { STB0899_UPKTERRORL , 0x00 }, { 0xffff , 0xff }, -- cgit v1.2.3 From 35afca912ffb8ea5a060ff53a59266ccaa769c98 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:47:30 -0300 Subject: V4L/DVB (13726): [Mantis/Skystar HD2] Add support for the Technisat Skystar HD2 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_vp1041.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 47cfb759f0b..a164bb14363 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -113,6 +113,7 @@ static void mantis_load_config(struct mantis_pci *mantis) mantis->hwconfig = &vp1034_mantis_config; break; case MANTIS_VP_1041_DVB_S2: // VP-1041 + case TECHNISAT_SKYSTAR_HD2: mantis->hwconfig = &vp1041_mantis_config; break; case MANTIS_VP_2033_DVB_C: // VP-2033 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index a4750bb22b0..9634b972a0f 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -240,6 +240,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; case MANTIS_VP_1041_DVB_S2: + case TECHNISAT_SKYSTAR_HD2: mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); if (mantis->fe) { dprintk(verbose, MANTIS_ERROR, 1, diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h index 53f4cb18857..2cc83a6e599 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.h +++ b/drivers/media/dvb/mantis/mantis_vp1041.h @@ -28,6 +28,7 @@ #include "lnbp21.h" #define MANTIS_VP_1041_DVB_S2 0x0031 +#define TECHNISAT_SKYSTAR_HD2 0x0001 extern struct mantis_hwconfig vp1041_mantis_config; extern struct stb0899_config vp1041_config; -- cgit v1.2.3 From 1159531a93f04346d94f72fdb4719c3f7e7d0a8c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:48:03 -0300 Subject: V4L/DVB (13727): [Mantis/VP-1041] Bugfix: Sigh! Don't look for the STOP bit Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_vp1041.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 8854ef390e0..7dee1af0d64 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -64,7 +64,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { { STB0899_IRQMSK_0 , 0xff }, { STB0899_IRQCFG , 0x00 }, { STB0899_I2CCFG , 0x88 }, - { STB0899_I2CRPT , 0x5c }, + { STB0899_I2CRPT , 0x58 }, { STB0899_IOPVALUE5 , 0x00 }, { STB0899_IOPVALUE4 , 0x33 }, { STB0899_IOPVALUE3 , 0x6d }, -- cgit v1.2.3 From 9ce39460837202920fb9bad88eeec13fc75e7a13 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:52:23 -0300 Subject: V4L/DVB (13728): [Mantis] Add in some Host Interface definitions Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.h | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_hif.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h new file mode 100644 index 00000000000..33b4f2b0ef6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -0,0 +1,9 @@ +#ifndef __MANTIS_HIF_H +#define __MANTIS_HIF_H + +#define MANTIS_HIF_MEMRD 1 +#define MANTIS_HIF_MEMWR 2 +#define MANTIS_HIF_IOMRD 3 +#define MANTIS_HIF_IOMWR 4 + +#endif // __MANTIS_HIF_H -- cgit v1.2.3 From 23fc1b2b00e849f6ec8628da77e2f282aedbebf3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:53:07 -0300 Subject: V4L/DVB (13729): [Mantis] Add in a license header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h index 33b4f2b0ef6..7ef45cec19d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_HIF_H #define __MANTIS_HIF_H -- cgit v1.2.3 From cb428c3fe9667eb7521769f25f65b9dbf52a33ca Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:59:05 -0300 Subject: V4L/DVB (13730): [Mantis] Add in some UART definitions Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_uart.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_uart.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h new file mode 100644 index 00000000000..6c9a17c3bfb --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -0,0 +1,18 @@ +#ifndef __MANTIS_UART_H +#define __MANTIS_UART_H + +enum mantis_baud { + MANTIS_BAUD_9600 = 0, + MANTIS_BAUD_19200, + MANTIS_BAUD_38400, + MANTIS_BAUD_57600, + MANTIS_BAUD_115200 +}; + +enum mantis_parity { + MANTIS_PARITY_NONE = 0, + MANTIS_PARITY_EVEN, + MANTIS_PARITY_ODD +}; + +#endif // __MANTIS_UART_H -- cgit v1.2.3 From d4f4ae046d2a9cd6b7ddb39e336a73ed92b63fe8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 04:59:44 -0300 Subject: V4L/DVB (13731): [Mantis] Add in a license header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_uart.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 6c9a17c3bfb..61138639c36 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_UART_H #define __MANTIS_UART_H -- cgit v1.2.3 From dd827da1e7d6ecf81883af68731cf0f1c2393c6d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:00:30 -0300 Subject: V4L/DVB (13732): [Mantis] Add in some Link Layer definitions Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_link.h | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_link.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h new file mode 100644 index 00000000000..2849457c427 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -0,0 +1,51 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __MANTIS_LINK_H +#define __MANTIS_LINK_H + +enum mantis_sbuf_status { + MANTIS_SBUF_DATA_AVAIL = 1, + MANTIS_SBUF_DATA_EMPTY = 2, + MANTIS_SBUF_DATA_OVFLW = 3 +}; + +struct mantis_slot { + u32 timeout; +}; + +struct mantis_ca { + struct mantis_slot slot; + + struct tasklet_struct hif_evm_tasklet; + + u32 hif_event; + wait_queue_head_t hif_opdone_wq; + wait_queue_head_t hif_brrdyw_wq; + wait_queue_head_t hif_data_wq; + u32 hif_job_queue + + enum mantis_sbuf_status sbuf_status; + + struct dvb_device *ca_dev; + void *ca_priv; +}; + +#endif // __MANTIS_LINK_H -- cgit v1.2.3 From bc4ed42fdf762a2049b255de92626ad1cfd86d8e Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:03:35 -0300 Subject: V4L/DVB (13733): [Mantis] Start with the PCMCIA interface Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 17 ++++++++-------- drivers/media/dvb/mantis/mantis_common.h | 4 ++++ drivers/media/dvb/mantis/mantis_link.h | 2 +- drivers/media/dvb/mantis/mantis_pcmcia.c | 34 ++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_pcmcia.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index bdf3e3629ab..fa9e806400e 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,11 +1,12 @@ -mantis-objs = mantis_core.o \ - mantis_dma.o \ - mantis_pci.o \ - mantis_i2c.o \ - mantis_dvb.o \ - mantis_vp1033.o \ - mantis_vp1034.o \ - mantis_vp1041.o \ +mantis-objs = mantis_core.o \ + mantis_dma.o \ + mantis_pci.o \ + mantis_i2c.o \ + mantis_dvb.o \ + mantis_pcmcia.o \ + mantis_vp1033.o \ + mantis_vp1034.o \ + mantis_vp1041.o \ mantis_vp2033.o \ mantis_vp2040.o \ mantis_vp3030.o diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 34d2389f312..24fc6da07fe 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -35,6 +35,8 @@ #include #include "mantis_reg.h" +#include "mantis_link.h" + #define MANTIS_ERROR 0 #define MANTIS_NOTICE 1 #define MANTIS_INFO 2 @@ -134,6 +136,8 @@ struct mantis_pci { /* A12 A13 A14 */ int gpio_status; + + struct mantis_ca *mantis_ca; }; extern unsigned int verbose; diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 2849457c427..2d9b64f6937 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -40,7 +40,7 @@ struct mantis_ca { wait_queue_head_t hif_opdone_wq; wait_queue_head_t hif_brrdyw_wq; wait_queue_head_t hif_data_wq; - u32 hif_job_queue + u32 hif_job_queue; enum mantis_sbuf_status sbuf_status; diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c new file mode 100644 index 00000000000..63f9621a90b --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -0,0 +1,34 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" + +int mantis_pcmcia_init(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + return 0; +} + +void mantis_pcmcia_exit(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + +} -- cgit v1.2.3 From d575571e8eda92c2cfd727ef050d17e30878fee6 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:04:18 -0300 Subject: V4L/DVB (13734): [Mantis] Initial go at an Event Manager Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_evm.c | 37 ++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_evm.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index fa9e806400e..38d0e6dbafe 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -3,6 +3,7 @@ mantis-objs = mantis_core.o \ mantis_pci.o \ mantis_i2c.o \ mantis_dvb.o \ + mantis_evm.o \ mantis_pcmcia.o \ mantis_vp1033.o \ mantis_vp1034.o \ diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 24fc6da07fe..f9891ebcfb0 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -77,6 +77,8 @@ struct mantis_hwconfig { }; struct mantis_pci { + unsigned int verbose; + /* PCI stuff */ u16 vendor_id; u16 device_id; diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c new file mode 100644 index 00000000000..c9359d6ddc2 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -0,0 +1,37 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_link.h" + +int mantis_evmgr_init(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + return 0; +} + +void mantis_evmgr_exit(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); +} -- cgit v1.2.3 From fadfa070d30434dd228362c933827eb6ce137f2d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:05:19 -0300 Subject: V4L/DVB (13735): [Mantis] Implement the Event Manager tasklet Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 65 +++++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_reg.h | 58 ++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index c9359d6ddc2..9f1740ea389 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -20,12 +20,76 @@ #include "mantis_common.h" #include "mantis_link.h" +#include "mantis_hif.h" + +void mantis_hifevm_tasklet(unsigned long data) +{ + struct mantis_ca *ca = (struct mantis_ca *) data; + struct mantis_pci *mantis = ca->ca_priv; + + u32 gpif_stat; + + gpif_stat = mmread(MANTIS_GPIF_STATUS); + + if (gpif_stat & MANTIS_GPIF_DETSTAT) { + if (gpif_stat & MANTIS_CARD_PLUGIN) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); + mmwrite(0xdada0000, MANTIS_CARD_RESET); + // Plugin call here + gpif_stat = 0; // crude ! + } + } else { + if (gpif_stat & MANTIS_CARD_PLUGOUT) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); + mmwrite(0xdada0000, MANTIS_CARD_RESET); + // Unplug call here + gpif_stat = 0; // crude ! + } + } + + if (gpif_stat & MANTIS_GPIF_EXTIRQ) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); + + if (gpif_stat & MANTIS_SBUF_WSTO) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); + + if (gpif_stat & MANTIS_GPIF_OTHERR) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); + + if (gpif_stat & MANTIS_SBUF_OVFLW) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); + + if (gpif_stat & MANTIS_GPIF_BRRDY) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); + ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; + if (ca->hif_job_queue & MANTIS_HIF_MEMRD) + wake_up(&ca->hif_brrdyw_wq); + } + if (gpif_stat & MANTIS_GPIF_WRACK) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); + + if (gpif_stat & MANTIS_GPIF_INTSTAT) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); + + if (gpif_stat & MANTIS_SBUF_EMPTY) + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); + + if (gpif_stat & MANTIS_SBUF_OPDONE) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); + if (ca->hif_job_queue) { + wake_up(&ca->hif_opdone_wq); + ca->hif_event = MANTIS_SBUF_OPDONE; + } + } +} int mantis_evmgr_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); + return 0; } @@ -34,4 +98,5 @@ void mantis_evmgr_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); + tasklet_kill(&ca->hif_evm_tasklet); } diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index 1b54e09fd86..d9862b7dbf0 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -73,6 +73,40 @@ #define MANTIS_I2C_STOP (0x01 << 5) #define MANTIS_I2C_PGMODE (0x01 << 3) +#define MANTIS_GPIF_CFGSLA 0x84 +#define MANTIS_GPIF_WAITSMPL (0x07 << 28) +#define MANTIS_GPIF_BYTEADDRSUB (0x01 << 25) +#define MANTIS_GPIF_WAITPOL (0x01 << 24) +#define MANTIS_GPIF_NCDELAY (0x07 << 20) +#define MANTIS_GPIF_RW2CSDELAY (0x07 << 16) +#define MANTIS_GPIF_SLFTIMEDMODE (0x01 << 15) +#define MANTIS_GPIF_SLFTIMEDDELY (0x7f << 8) +#define MANTIS_GPIF_DEVTYPE (0x07 << 4) +#define MANTIS_GPIF_BIGENDIAN (0x01 << 3) +#define MANTIS_GPIF_FETCHCMD (0x03 << 1) +#define MANTIS_GPIF_HWORDDEV (0x01 << 0) + +#define MANTIS_GPIF_WSTOPER 0x90 +#define MANTIS_GPIF_WSTOPERWREN3 (0x01 << 31) +#define MANTIS_GPIF_PARBOOTN (0x01 << 29) +#define MANTIS_GPIF_WSTOPERSLID3 (0x1f << 24) +#define MANTIS_GPIF_WSTOPERWREN2 (0x01 << 23) +#define MANTIS_GPIF_WSTOPERSLID2 (0x1f << 16) +#define MANTIS_GPIF_WSTOPERWREN1 (0x01 << 15) +#define MANTIS_GPIF_WSTOPERSLID1 (0x1f << 8) +#define MANTIS_GPIF_WSTOPERWREN0 (0x01 << 7) +#define MANTIS_GPIF_WSTOPERSLID0 (0x1f << 0) + +#define MANTIS_GPIF_CS2RW 0x94 +#define MANTIS_GPIF_CS2RWWREN3 (0x01 << 31) +#define MANTIS_GPIF_CS2RWDELY3 (0x3f << 24) +#define MANTIS_GPIF_CS2RWWREN2 (0x01 << 23) +#define MANTIS_GPIF_CS2RWDELY2 (0x3f << 16) +#define MANTIS_GPIF_CS2RWWREN1 (0x01 << 15) +#define MANTIS_GPIF_CS2RWDELY1 (0x3f << 8) +#define MANTIS_GPIF_CS2RWWREN0 (0x01 << 7) +#define MANTIS_GPIF_CS2RWDELY0 (0x3f << 0) + #define MANTIS_GPIF_IRQCFG 0x98 #define MANTIS_GPIF_IRQPOL (0x01 << 8) #define MANTIS_MASK_WRACK (0x01 << 7) @@ -99,11 +133,33 @@ #define MANTIS_CARD_PLUGIN (0x01 << 1) #define MANTIS_CARD_PLUGOUT (0x01 << 0) +#define MANTIS_GPIF_BRADDR 0xa0 +#define MANTIS_GPIF_PCMCIAREG (0x01 << 27) +#define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) +#define MANTIS_GPIF_BR_ADDR (0xfffffff << 0) + +#define MANTIS_GPIF_BRBYTES 0xa4 +#define MANTIS_GPIF_BRCNT (0xfff << 0) + +#define MANTIS_PCMCIA_RESET 0xa8 +#define MANTIS_PCMCIA_RSTVAL (0xff << 0) + +#define MANTIS_CARD_RESET 0xac + #define MANTIS_GPIF_ADDR 0xb0 -#define MANTIS_GPIF_RDWRN (0x01 << 31) +#define MANTIS_GPIF_RDWRN (0x01 << 31) +#define MANTIS_GPIF_PCMCIAREG (0x01 << 27) +#define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) +#define MANTIS_GPIF_HIF_ADDR (0xfffffff << 0) #define MANTIS_GPIF_DOUT 0xb4 +#define MANTIS_GPIF_HIF_DOUT (0xfffffff << 0) + #define MANTIS_GPIF_DIN 0xb8 +#define MANTIS_GPIF_HIF_DIN (0xfffffff << 0) +#define MANTIS_GPIF_SPARE 0xbc +#define MANTIS_GPIF_LOGICRD (0xffff << 16) +#define MANTIS_GPIF_LOGICRW (0xffff << 0) #endif //__MANTIS_REG_H -- cgit v1.2.3 From 8ce571f5e7eb7186f676af3b60af7980c2fc7929 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:06:00 -0300 Subject: V4L/DVB (13736): [Mantis] Implement CAM Plug IN and Unplug events Sigh! how i wish things were simpler ... Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_link.h | 8 ++++ drivers/media/dvb/mantis/mantis_pcmcia.c | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 2d9b64f6937..c6b32229edd 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -31,6 +31,12 @@ struct mantis_slot { u32 timeout; }; +/* Physical layer */ +enum mantis_slot_state { + MODULE_INSERTED = 3, + MODULE_XTRACTED = 4 +}; + struct mantis_ca { struct mantis_slot slot; @@ -44,6 +50,8 @@ struct mantis_ca { enum mantis_sbuf_status sbuf_status; + enum mantis_slot_state slot_state; + struct dvb_device *ca_dev; void *ca_priv; }; diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 63f9621a90b..960123f1ed4 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -19,11 +19,75 @@ */ #include "mantis_common.h" +#include "mantis_link.h" /* temporary due to physical layer stuff */ + +/* + * If Slot state is already PLUG_IN event and we are called + * again, definitely it is jitter alone + */ +void mantis_event_cam_plugin(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + u32 gpif_irqcfg; + + if (ca->slot_state == MODULE_XTRACTED) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); + udelay(50); + mmwrite(0xda000000, MANTIS_CARD_RESET); + gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); + gpif_irqcfg |= MANTIS_MASK_PLUGOUT; + gpif_irqcfg &= ~MANTIS_MASK_PLUGIN; + mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG); + udelay(500); + ca->slot_state = MODULE_INSERTED; + } + udelay(100); +} + +/* + * If Slot state is already UN_PLUG event and we are called + * again, definitely it is jitter alone + */ +void mantis_event_cam_unplug(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + + u32 gpif_irqcfg; + + if (ca->slot_state == MODULE_INSERTED) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); + udelay(50); + mmwrite(0x00da0000, MANTIS_CARD_RESET); + gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); + gpif_irqcfg |= MANTIS_MASK_PLUGIN; + gpif_irqcfg &= ~MANTIS_MASK_PLUGOUT; + mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG); + udelay(500); + ca->slot_state = MODULE_XTRACTED; + } + udelay(100); +} int mantis_pcmcia_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; + u32 gpif_stat, card_stat; + + gpif_stat = mmread(MANTIS_GPIF_STATUS); + card_stat = mmread(MANTIS_GPIF_IRQCFG); + + if (gpif_stat & MANTIS_GPIF_DETSTAT) { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); + mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); + ca->slot_state = MODULE_INSERTED; + } else { + dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); + mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); + ca->slot_state = MODULE_XTRACTED; + } + return 0; } @@ -31,4 +95,6 @@ void mantis_pcmcia_exit(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; + mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS); + mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK); } -- cgit v1.2.3 From 50d82602760c99d2c954c33360990c00146532cd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:06:38 -0300 Subject: V4L/DVB (13737): [Mantis] Register the CA device, dummy functions for now Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_ca.c | 127 +++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_evm.c | 4 ++ drivers/media/dvb/mantis/mantis_link.h | 8 +++ 4 files changed, 140 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_ca.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index 38d0e6dbafe..c4da0d8ed18 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -4,6 +4,7 @@ mantis-objs = mantis_core.o \ mantis_i2c.o \ mantis_dvb.o \ mantis_evm.o \ + mantis_ca.o \ mantis_pcmcia.o \ mantis_vp1033.o \ mantis_vp1034.o \ diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c new file mode 100644 index 00000000000..6e440d31b79 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -0,0 +1,127 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_link.h" +#include "mantis_hif.h" + + +static int mantis_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long parg) +{ + return 0; +} + +static int mantis_ca_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int mantis_ca_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t mantis_ca_read(struct file *file, char __user *buffer, size_t count, loff_t *ofset) +{ + struct dvb_device *dvbdev = file->private_data; + struct mantis_ca *ca = dvbdev->priv; + + int status; + + return 0; +error: + return status; +} + +static ssize_t mantis_ca_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) +{ + struct dvb_device *dvbdev = file->private_data; + struct mantis_ca *ca = dvbdev->priv; + + int status; + + return 0; +error: + return status; +} + +static struct file_operations mantis_fops = { + .owner = THIS_MODULE, + .ioctl = mantis_ca_ioctl, + .open = mantis_ca_open, + .release = mantis_ca_release, + .read = mantis_ca_read, + .write = mantis_ca_write, +}; + +static struct dvb_device mantis_ca = { + .priv = NULL, + .users = 1, + .readers = 1, + .writers = 1, + .fops = &mantis_fops, +}; + +struct dvb_device *mantis_ca_init(struct mantis_pci *mantis) +{ + int ret; + + struct dvb_device *dvbdev; + struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; + struct mantis_ca *ca; + + if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { + dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); + return NULL; + } + + ca->ca_priv = mantis; + mantis->mantis_ca = ca; + mantis_evmgr_init(ca); + + dprintk(verbose, MANTIS_ERROR, 0, "CA: Registering Mantis Adapter(%d) Slot(0)\n", mantis->num); + if (dvb_register_device(dvb_adapter, &dvbdev, &mantis_ca, ca, DVB_DEVICE_CA) == 0) { + ca->ca_dev = dvbdev; + return ca->ca_dev; + } + return 0; + +error: + if (ca != NULL) { + dprintk(verbose, MANTIS_ERROR, 1, "Error .."); + if (ca->ca_dev != NULL) + dvb_unregister_device(ca->ca_dev); + + kfree(ca); + } + return NULL; +} + +void mantis_ca_exit(struct mantis_pci *mantis) +{ + struct mantis_ca *ca = mantis->mantis_ca; + + mantis_evmgr_exit(ca); + dprintk(verbose, MANTIS_ERROR, 0, "CA: Unregister Mantis Adapter(%d) Slot(0)\n", mantis->num); + if (ca->ca_dev) + dvb_unregister_device(ca->ca_dev); + + kfree(ca); +} diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9f1740ea389..c4a1c89431e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -90,6 +90,8 @@ int mantis_evmgr_init(struct mantis_ca *ca) dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); + mantis_pcmcia_init(ca); + return 0; } @@ -99,4 +101,6 @@ void mantis_evmgr_exit(struct mantis_ca *ca) dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); tasklet_kill(&ca->hif_evm_tasklet); + + mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index c6b32229edd..a45dd7185e0 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -56,4 +56,12 @@ struct mantis_ca { void *ca_priv; }; +/* CA */ +extern void mantis_event_cam_plugin(struct mantis_ca *ca); +extern void mantis_event_cam_unplug(struct mantis_ca *ca); +extern int mantis_pcmcia_init(struct mantis_ca *ca); +extern void mantis_pcmcia_exit(struct mantis_ca *ca); +extern int mantis_evmgr_init(struct mantis_ca *ca); +extern void mantis_evmgr_exit(struct mantis_ca *ca); + #endif // __MANTIS_LINK_H -- cgit v1.2.3 From d9dd5f7168d6a61491996fc02e4deb9d96308178 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:07:41 -0300 Subject: V4L/DVB (13738): [Mantis] Enable IRQ0 events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 4 ++-- drivers/media/dvb/mantis/mantis_dvb.c | 2 ++ drivers/media/dvb/mantis/mantis_evm.c | 26 +++++++++++++------------- drivers/media/dvb/mantis/mantis_pci.c | 10 ++++------ drivers/media/dvb/mantis/mantis_pcmcia.c | 9 +++++---- 5 files changed, 26 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 6e440d31b79..e6de3c9d3ce 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -93,12 +93,12 @@ struct dvb_device *mantis_ca_init(struct mantis_pci *mantis) } ca->ca_priv = mantis; - mantis->mantis_ca = ca; - mantis_evmgr_init(ca); dprintk(verbose, MANTIS_ERROR, 0, "CA: Registering Mantis Adapter(%d) Slot(0)\n", mantis->num); if (dvb_register_device(dvb_adapter, &dvbdev, &mantis_ca, ca, DVB_DEVICE_CA) == 0) { ca->ca_dev = dvbdev; + mantis->mantis_ca = ca; + mantis_evmgr_init(ca); return ca->ca_dev; } return 0; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 9634b972a0f..3325b59ce19 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -190,6 +190,8 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); mantis_frontend_init(mantis); + mantis_ca_init(mantis); + return 0; /* Error conditions .. */ diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index c4a1c89431e..d81068d0834 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -33,14 +33,14 @@ void mantis_hifevm_tasklet(unsigned long data) if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); // Plugin call here gpif_stat = 0; // crude ! } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); // Unplug call here gpif_stat = 0; // crude ! @@ -48,34 +48,34 @@ void mantis_hifevm_tasklet(unsigned long data) } if (gpif_stat & MANTIS_GPIF_EXTIRQ) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); if (gpif_stat & MANTIS_SBUF_WSTO) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); if (gpif_stat & MANTIS_GPIF_OTHERR) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); if (gpif_stat & MANTIS_SBUF_OVFLW) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); if (gpif_stat & MANTIS_GPIF_BRRDY) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; if (ca->hif_job_queue & MANTIS_HIF_MEMRD) wake_up(&ca->hif_brrdyw_wq); } if (gpif_stat & MANTIS_GPIF_WRACK) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); if (gpif_stat & MANTIS_GPIF_INTSTAT) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); if (gpif_stat & MANTIS_SBUF_EMPTY) - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); if (gpif_stat & MANTIS_SBUF_OPDONE) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); if (ca->hif_job_queue) { wake_up(&ca->hif_opdone_wq); ca->hif_event = MANTIS_SBUF_OPDONE; @@ -87,7 +87,7 @@ int mantis_evmgr_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); mantis_pcmcia_init(ca); @@ -99,7 +99,7 @@ void mantis_evmgr_exit(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); tasklet_kill(&ca->hif_evm_tasklet); mantis_pcmcia_exit(ca); diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 402f866e12d..814c6ace3d3 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -54,12 +54,15 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) { u32 stat = 0, mask = 0, lstat = 0, mstat = 0; struct mantis_pci *mantis; + struct mantis_ca *ca; mantis = (struct mantis_pci *) dev_id; if (unlikely(mantis == NULL)) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); return IRQ_NONE; } + ca = mantis->mantis_ca; + stat = mmread(MANTIS_INT_STAT); mask = mmread(MANTIS_INT_MASK); mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; @@ -72,14 +75,9 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) if (stat & MANTIS_INT_RISCEN) { dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); } - if (stat & MANTIS_INT_I2CRACK) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C R-ACK *"); - } - if (stat & MANTIS_INT_PCMCIA7) { - dprintk(verbose, MANTIS_DEBUG, 0, "* PCMCIA-07 *"); - } if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + tasklet_schedule(&ca->hif_evm_tasklet); } if (stat & MANTIS_INT_IRQ1) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 960123f1ed4..47cc720d35d 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -32,7 +32,7 @@ void mantis_event_cam_plugin(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_XTRACTED) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0xda000000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -56,7 +56,7 @@ void mantis_event_cam_unplug(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_INSERTED) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0x00da0000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -75,15 +75,16 @@ int mantis_pcmcia_init(struct mantis_ca *ca) u32 gpif_stat, card_stat; + mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK); gpif_stat = mmread(MANTIS_GPIF_STATUS); card_stat = mmread(MANTIS_GPIF_IRQCFG); if (gpif_stat & MANTIS_GPIF_DETSTAT) { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_INSERTED; } else { - dprintk(mantis->verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); + dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_XTRACTED; } -- cgit v1.2.3 From 3062b1571a1d3520c4d3160ebbfca8002b1d6963 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:08:25 -0300 Subject: V4L/DVB (13739): [Mantis] Event Manager: Handle Masked events only Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_evm.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 3325b59ce19..ade444963c8 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -313,6 +313,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) int __devexit mantis_dvb_exit(struct mantis_pci *mantis) { + mantis_ca_exit(mantis); tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index d81068d0834..c35ddd868f8 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -27,9 +27,12 @@ void mantis_hifevm_tasklet(unsigned long data) struct mantis_ca *ca = (struct mantis_ca *) data; struct mantis_pci *mantis = ca->ca_priv; - u32 gpif_stat; + u32 gpif_stat, gpif_mask; gpif_stat = mmread(MANTIS_GPIF_STATUS); + gpif_mask = mmread(MANTIS_GPIF_IRQCFG); + if (!((gpif_stat & 0xff) & (gpif_mask & 0xff))) + return; if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { -- cgit v1.2.3 From 12855cac87218d0c92ffdebb7270cec040cf5a6a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:09:04 -0300 Subject: V4L/DVB (13740): [Mantis] Schedule the work instead of handling the task directly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 4 ++++ drivers/media/dvb/mantis/mantis_evm.c | 17 +++++++---------- drivers/media/dvb/mantis/mantis_link.h | 4 +++- drivers/media/dvb/mantis/mantis_pci.c | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index f9891ebcfb0..7f1cfad7488 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -151,4 +151,8 @@ extern int mantis_dvb_exit(struct mantis_pci *mantis); extern void mantis_dma_xfer(unsigned long data); extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); +extern struct dvb_device *mantis_ca_init(struct mantis_pci *mantis); +extern void mantis_ca_exit(struct mantis_pci *mantis); + + #endif //__MANTIS_COMMON_H diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index c35ddd868f8..74514839998 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -22,9 +22,9 @@ #include "mantis_link.h" #include "mantis_hif.h" -void mantis_hifevm_tasklet(unsigned long data) +static void mantis_hifevm_work(struct work_struct *work) { - struct mantis_ca *ca = (struct mantis_ca *) data; + struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); struct mantis_pci *mantis = ca->ca_priv; u32 gpif_stat, gpif_mask; @@ -38,15 +38,13 @@ void mantis_hifevm_tasklet(unsigned long data) if (gpif_stat & MANTIS_CARD_PLUGIN) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); - // Plugin call here - gpif_stat = 0; // crude ! + mantis_event_cam_plugin(ca); } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); - // Unplug call here - gpif_stat = 0; // crude ! + mantis_event_cam_unplug(ca); } } @@ -91,9 +89,9 @@ int mantis_evmgr_init(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); - tasklet_init(&ca->hif_evm_tasklet, mantis_hifevm_tasklet, (unsigned long) ca); - + INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); mantis_pcmcia_init(ca); + schedule_work(&ca->hif_evm_work); return 0; } @@ -103,7 +101,6 @@ void mantis_evmgr_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); - tasklet_kill(&ca->hif_evm_tasklet); - + flush_scheduled_work(); mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index a45dd7185e0..33b39b781d2 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -21,6 +21,8 @@ #ifndef __MANTIS_LINK_H #define __MANTIS_LINK_H +#include + enum mantis_sbuf_status { MANTIS_SBUF_DATA_AVAIL = 1, MANTIS_SBUF_DATA_EMPTY = 2, @@ -40,7 +42,7 @@ enum mantis_slot_state { struct mantis_ca { struct mantis_slot slot; - struct tasklet_struct hif_evm_tasklet; + struct work_struct hif_evm_work; u32 hif_event; wait_queue_head_t hif_opdone_wq; diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 814c6ace3d3..6eecd54a445 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -77,7 +77,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); - tasklet_schedule(&ca->hif_evm_tasklet); + schedule_work(&ca->hif_evm_work); } if (stat & MANTIS_INT_IRQ1) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); -- cgit v1.2.3 From d8b14f8a76d71c84622a211f57baf15f61cc9703 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:09:47 -0300 Subject: V4L/DVB (13741): [Mantis] Implement HIF Mem Read/Write operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 1 + drivers/media/dvb/mantis/mantis_dma.c | 4 +- drivers/media/dvb/mantis/mantis_evm.c | 3 +- drivers/media/dvb/mantis/mantis_hif.c | 139 +++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 10 ++- drivers/media/dvb/mantis/mantis_reg.h | 8 +- 6 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_hif.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index c4da0d8ed18..d002ef9f744 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -4,6 +4,7 @@ mantis-objs = mantis_core.o \ mantis_i2c.o \ mantis_dvb.o \ mantis_evm.o \ + mantis_hif.o \ mantis_ca.o \ mantis_pcmcia.o \ mantis_vp1033.o \ diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index f685992f7d0..250f49a913a 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,7 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(mantis->risc_dma, MANTIS_RISC_START); - mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_RDWRN, MANTIS_GPIF_ADDR); + mmwrite(mmread(MANTIS_GPIF_HIFADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_HIFADDR); mmwrite(0, MANTIS_DMA_CTL); mantis->last_block = mantis->finished_block = 0; @@ -210,7 +210,7 @@ void mantis_dma_stop(struct mantis_pci *mantis) mask = mmread(MANTIS_INT_MASK); dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); - mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_RDWRN))), MANTIS_GPIF_ADDR); + mmwrite((mmread(MANTIS_GPIF_HIFADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_HIFADDR); mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | MANTIS_DCAP_EN | diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 74514839998..dbcdca3a8f0 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -92,7 +92,7 @@ int mantis_evmgr_init(struct mantis_ca *ca) INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); mantis_pcmcia_init(ca); schedule_work(&ca->hif_evm_work); - + mantis_hif_init(ca); return 0; } @@ -102,5 +102,6 @@ void mantis_evmgr_exit(struct mantis_ca *ca) dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); flush_scheduled_work(); + mantis_hif_exit(ca); mantis_pcmcia_exit(ca); } diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c new file mode 100644 index 00000000000..1472008e257 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -0,0 +1,139 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_hif.h" +#include "mantis_link.h" /* temporary due to physical layer stuff */ + +static int mantis_hif_data_available(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + int rc = 0; + + if (wait_event_interruptible_timeout(ca->hif_data_wq, + ca->sbuf_status & MANTIS_SBUF_DATA_AVAIL, + msecs_to_jiffies(500)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); + rc = -EREMOTEIO; + } + ca->sbuf_status &= ~MANTIS_SBUF_DATA_AVAIL; + udelay(2); + return rc; +} + +static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + int rc = 0; + + if (wait_event_interruptible_timeout(ca->hif_opdone_wq, + ca->hif_event & MANTIS_SBUF_OPDONE, + msecs_to_jiffies(500)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); + rc = -EREMOTEIO; + } + ca->hif_event &= ~MANTIS_SBUF_OPDONE; + udelay(5); + return rc; +} + +int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0, data, count = 4; + + hif_addr |= MANTIS_GPIF_HIFRDWRN; + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(hif_addr, MANTIS_GPIF_BRADDR); + mmwrite(count, MANTIS_GPIF_BRBYTES); + + udelay(20); + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + if (mantis_hif_data_available(ca) != 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer burst read failed", mantis->num); + return -EREMOTEIO; + } + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + data = mmread(MANTIS_GPIF_HIFDIN); + + return (data >> 24) & 0xff; +} + +int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) +{ + struct mantis_slot *slot = ca->slot; + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0; + + hif_addr &= ~MANTIS_GPIF_HIFRDWRN; + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(data, MANTIS_GPIF_HIFDOUT); + ca->hif_job_queue = MANTIS_HIF_MEMWR; + + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; + return 0; +} + +int mantis_hif_init(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 irqcfg; + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); + init_waitqueue_head(&ca->hif_data_wq); + init_waitqueue_head(&ca->hif_opdone_wq); + + irqcfg = mmread(MANTIS_GPIF_IRQCFG); + irqcfg |= MANTIS_MASK_BRRDY; + mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); + + return 0; +} + +void mantis_hif_exit(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 irqcfg; + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); + irqcfg = mmread(MANTIS_GPIF_IRQCFG); + irqcfg &= ~MANTIS_MASK_BRRDY; + mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); +} diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 33b39b781d2..8862502866c 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -31,6 +31,8 @@ enum mantis_sbuf_status { struct mantis_slot { u32 timeout; + u32 slave_cfg; + u32 bar; }; /* Physical layer */ @@ -40,7 +42,7 @@ enum mantis_slot_state { }; struct mantis_ca { - struct mantis_slot slot; + struct mantis_slot slot[4]; struct work_struct hif_evm_work; @@ -66,4 +68,10 @@ extern void mantis_pcmcia_exit(struct mantis_ca *ca); extern int mantis_evmgr_init(struct mantis_ca *ca); extern void mantis_evmgr_exit(struct mantis_ca *ca); +/* HIF */ +extern int mantis_hif_init(struct mantis_ca *ca); +extern void mantis_hif_exit(struct mantis_ca *ca); +extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); +extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); + #endif // __MANTIS_LINK_H diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index d9862b7dbf0..6f5cd493676 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -147,16 +147,16 @@ #define MANTIS_CARD_RESET 0xac #define MANTIS_GPIF_ADDR 0xb0 -#define MANTIS_GPIF_RDWRN (0x01 << 31) +#define MANTIS_GPIF_HIFRDWRN (0x01 << 31) #define MANTIS_GPIF_PCMCIAREG (0x01 << 27) #define MANTIS_GPIF_PCMCIAIOM (0x01 << 26) -#define MANTIS_GPIF_HIF_ADDR (0xfffffff << 0) +#define MANTIS_GPIF_HIFADDR (0xfffffff << 0) #define MANTIS_GPIF_DOUT 0xb4 -#define MANTIS_GPIF_HIF_DOUT (0xfffffff << 0) +#define MANTIS_GPIF_HIFDOUT (0xfffffff << 0) #define MANTIS_GPIF_DIN 0xb8 -#define MANTIS_GPIF_HIF_DIN (0xfffffff << 0) +#define MANTIS_GPIF_HIFDIN (0xfffffff << 0) #define MANTIS_GPIF_SPARE 0xbc #define MANTIS_GPIF_LOGICRD (0xffff << 16) -- cgit v1.2.3 From c9a750c909cbde15ecd0f8545f48e051bfee6271 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:10:25 -0300 Subject: V4L/DVB (13742): [Mantis] Implement PCMCIA I/O Rd/Wr operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 54 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 2 ++ 2 files changed, 56 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 1472008e257..42aedf7a014 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -111,6 +111,60 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) return 0; } +int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0; + + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr |= MANTIS_GPIF_HIFRDWRN; + hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + ca->hif_job_queue = MANTIS_HIF_IOMRD; + + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + udelay(50); + ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; + *data = mmread(MANTIS_GPIF_HIFDIN); + hif_addr |= MANTIS_GPIF_PCMCIAREG; + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + + return 0; +} + +int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 hif_addr = 0; + + hif_addr &= ~MANTIS_GPIF_PCMCIAREG; + hif_addr &= ~MANTIS_GPIF_HIFRDWRN; + hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= addr; + + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(data, MANTIS_GPIF_HIFDOUT); + + ca->hif_job_queue = MANTIS_HIF_IOMWR; + if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + return -EREMOTEIO; + } + udelay(50); + ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; + hif_addr |= MANTIS_GPIF_PCMCIAREG; + mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + + return 0; +} + int mantis_hif_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 8862502866c..478900ea184 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -73,5 +73,7 @@ extern int mantis_hif_init(struct mantis_ca *ca); extern void mantis_hif_exit(struct mantis_ca *ca); extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); +extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data); +extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data); #endif // __MANTIS_LINK_H -- cgit v1.2.3 From 6053240f5cc914d40ac9c7afe15008bf3e46359c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:11:14 -0300 Subject: V4L/DVB (13743): [Mantis CA] Use DVB_CA Tuple parser Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 129 ++++++++++++++++--------------- drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_hif.c | 10 +-- drivers/media/dvb/mantis/mantis_link.h | 9 ++- 4 files changed, 80 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index e6de3c9d3ce..4be61ca02c2 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -22,96 +22,104 @@ #include "mantis_link.h" #include "mantis_hif.h" - -static int mantis_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long parg) +static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) { - return 0; + struct mantis_ca *ca = en50221->data; + + if (slot != 0) + return -EINVAL; + + return mantis_hif_read_mem(ca, addr); } -static int mantis_ca_open(struct inode *inode, struct file *file) +static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data) { - return 0; + struct mantis_ca *ca = en50221->data; + + if (slot != 0) + return -EINVAL; + + return mantis_hif_write_mem(ca, addr, data); } -static int mantis_ca_release(struct inode *inode, struct file *file) +static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) { - return 0; + struct mantis_ca *ca = en50221->data; + + if (slot != 0) + return -EINVAL; + + return mantis_hif_read_iom(ca, addr); } -static ssize_t mantis_ca_read(struct file *file, char __user *buffer, size_t count, loff_t *ofset) +static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) { - struct dvb_device *dvbdev = file->private_data; - struct mantis_ca *ca = dvbdev->priv; + struct mantis_ca *ca = en50221->data; - int status; + if (slot != 0) + return -EINVAL; - return 0; -error: - return status; + return mantis_hif_write_iom(ca, addr, data); } -static ssize_t mantis_ca_write(struct file *file, const char __user *buffer, size_t count, loff_t *offset) +static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) { - struct dvb_device *dvbdev = file->private_data; - struct mantis_ca *ca = dvbdev->priv; + return 0; +} - int status; +static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) +{ + return 0; +} +static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) +{ return 0; -error: - return status; } -static struct file_operations mantis_fops = { - .owner = THIS_MODULE, - .ioctl = mantis_ca_ioctl, - .open = mantis_ca_open, - .release = mantis_ca_release, - .read = mantis_ca_read, - .write = mantis_ca_write, -}; - -static struct dvb_device mantis_ca = { - .priv = NULL, - .users = 1, - .readers = 1, - .writers = 1, - .fops = &mantis_fops, -}; - -struct dvb_device *mantis_ca_init(struct mantis_pci *mantis) +static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) { - int ret; + return 0; +} - struct dvb_device *dvbdev; +int mantis_ca_init(struct mantis_pci *mantis) +{ struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; struct mantis_ca *ca; + int ca_flags = 0, result; if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); - return NULL; + result = -ENOMEM; + goto err; } ca->ca_priv = mantis; - - dprintk(verbose, MANTIS_ERROR, 0, "CA: Registering Mantis Adapter(%d) Slot(0)\n", mantis->num); - if (dvb_register_device(dvb_adapter, &dvbdev, &mantis_ca, ca, DVB_DEVICE_CA) == 0) { - ca->ca_dev = dvbdev; - mantis->mantis_ca = ca; - mantis_evmgr_init(ca); - return ca->ca_dev; + mantis->mantis_ca = ca; + + /* register CA interface */ + ca->en50221.owner = THIS_MODULE; + ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; + ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem; + ca->en50221.read_cam_control = mantis_ca_read_cam_ctl; + ca->en50221.write_cam_control = mantis_ca_write_cam_ctl; + ca->en50221.slot_reset = mantis_ca_slot_reset; + ca->en50221.slot_shutdown = mantis_ca_slot_shutdown; + ca->en50221.slot_ts_enable = mantis_ts_control; + ca->en50221.poll_slot_status = mantis_slot_status; + ca->en50221.data = ca; + + dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); + if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { + dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); + goto err; } + dprintk(verbose, MANTIS_ERROR, 1, "Registered EN50221 device"); + mantis_evmgr_init(ca); return 0; - -error: - if (ca != NULL) { - dprintk(verbose, MANTIS_ERROR, 1, "Error .."); - if (ca->ca_dev != NULL) - dvb_unregister_device(ca->ca_dev); - - kfree(ca); - } - return NULL; +err: + kfree(ca); + return result; } void mantis_ca_exit(struct mantis_pci *mantis) @@ -119,9 +127,8 @@ void mantis_ca_exit(struct mantis_pci *mantis) struct mantis_ca *ca = mantis->mantis_ca; mantis_evmgr_exit(ca); - dprintk(verbose, MANTIS_ERROR, 0, "CA: Unregister Mantis Adapter(%d) Slot(0)\n", mantis->num); - if (ca->ca_dev) - dvb_unregister_device(ca->ca_dev); + dprintk(verbose, MANTIS_ERROR, 1, "Unregistering EN50221 device"); + dvb_ca_en50221_release(&ca->en50221); kfree(ca); } diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 7f1cfad7488..0aa4001dea9 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -151,7 +151,7 @@ extern int mantis_dvb_exit(struct mantis_pci *mantis); extern void mantis_dma_xfer(unsigned long data); extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); -extern struct dvb_device *mantis_ca_init(struct mantis_pci *mantis); +extern int mantis_ca_init(struct mantis_pci *mantis); extern void mantis_ca_exit(struct mantis_pci *mantis); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 42aedf7a014..6a1ea96c16d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -111,10 +111,10 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) return 0; } -int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data) +int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) { struct mantis_pci *mantis = ca->ca_priv; - u32 hif_addr = 0; + u32 data, hif_addr = 0; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_HIFRDWRN; @@ -131,14 +131,14 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data) } udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; - *data = mmread(MANTIS_GPIF_HIFDIN); + data = mmread(MANTIS_GPIF_HIFDIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); - return 0; + return data; } -int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data) +int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) { struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 478900ea184..23ff2d6aadb 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -22,6 +22,7 @@ #define __MANTIS_LINK_H #include +#include "dvb_ca_en50221.h" enum mantis_sbuf_status { MANTIS_SBUF_DATA_AVAIL = 1, @@ -56,8 +57,10 @@ struct mantis_ca { enum mantis_slot_state slot_state; - struct dvb_device *ca_dev; +// struct dvb_device *ca_dev; void *ca_priv; + + struct dvb_ca_en50221 en50221; }; /* CA */ @@ -73,7 +76,7 @@ extern int mantis_hif_init(struct mantis_ca *ca); extern void mantis_hif_exit(struct mantis_ca *ca); extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr); extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); -extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr, u32 count, u32 *data); -extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u32 data); +extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr); +extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data); #endif // __MANTIS_LINK_H -- cgit v1.2.3 From 4e9fbeeedc22d287b5d05e32bbc647cd2dc8c663 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:11:41 -0300 Subject: V4L/DVB (13744): [Mantis CA] Use Module status to signal Slot events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 4be61ca02c2..cd6bed73729 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -79,6 +79,11 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) { + struct mantis_ca *ca = en50221->data; + + if (ca->slot_state == MODULE_INSERTED) + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + return 0; } -- cgit v1.2.3 From 2133ffbf08e7fca0614ea73cb5c43cc6435b4414 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:12:16 -0300 Subject: V4L/DVB (13745): [Mantis CA] Add some debug statements Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 34 ++++++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_hif.c | 4 ++++ 2 files changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index cd6bed73729..a8b8c88238e 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -25,6 +25,9 @@ static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); if (slot != 0) return -EINVAL; @@ -35,6 +38,9 @@ static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); if (slot != 0) return -EINVAL; @@ -45,6 +51,9 @@ static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, in static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); if (slot != 0) return -EINVAL; @@ -55,6 +64,9 @@ static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 a static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); if (slot != 0) return -EINVAL; @@ -64,22 +76,40 @@ static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) { + struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); + return 0; } static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) { + struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); + return 0; } static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) { + struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); + return 0; } static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) { struct mantis_ca *ca = en50221->data; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); if (ca->slot_state == MODULE_INSERTED) return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; @@ -93,6 +123,7 @@ int mantis_ca_init(struct mantis_pci *mantis) struct mantis_ca *ca; int ca_flags = 0, result; + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis CA"); if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); result = -ENOMEM; @@ -130,6 +161,9 @@ err: void mantis_ca_exit(struct mantis_pci *mantis) { struct mantis_ca *ca = mantis->mantis_ca; + struct mantis_pci *mantis = ca->ca_priv; + + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis CA exit"); mantis_evmgr_exit(ca); dprintk(verbose, MANTIS_ERROR, 1, "Unregistering EN50221 device"); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 6a1ea96c16d..42e0360e96d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -61,6 +61,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0, data, count = 4; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -91,6 +92,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -116,6 +118,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 data, hif_addr = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; @@ -143,6 +146,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; + dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; -- cgit v1.2.3 From fbe1e43abc6ada6bcd3e9866b01e41f093f12c62 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:12:51 -0300 Subject: V4L/DVB (13746): [Mantis CA] Bug: Remove duplicated symbol Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index a8b8c88238e..f6d70cb3f6f 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -161,7 +161,6 @@ err: void mantis_ca_exit(struct mantis_pci *mantis) { struct mantis_ca *ca = mantis->mantis_ca; - struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Mantis CA exit"); -- cgit v1.2.3 From a0c59063a7fe92524ab8fa6e31997b177a8f3029 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:13:21 -0300 Subject: V4L/DVB (13747): [Mantis] Bug Fix!: Use Register Address rather than register field Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dma.c | 4 ++-- drivers/media/dvb/mantis/mantis_hif.c | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 250f49a913a..d15a1eb980c 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -190,7 +190,7 @@ void mantis_dma_start(struct mantis_pci *mantis) mantis_risc_program(mantis); mmwrite(mantis->risc_dma, MANTIS_RISC_START); - mmwrite(mmread(MANTIS_GPIF_HIFADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_HIFADDR); + mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); mmwrite(0, MANTIS_DMA_CTL); mantis->last_block = mantis->finished_block = 0; @@ -210,7 +210,7 @@ void mantis_dma_stop(struct mantis_pci *mantis) mask = mmread(MANTIS_INT_MASK); dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); - mmwrite((mmread(MANTIS_GPIF_HIFADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_HIFADDR); + mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | MANTIS_DCAP_EN | diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 42e0360e96d..9e058be8726 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -72,7 +72,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) udelay(20); - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); if (mantis_hif_data_available(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer burst read failed", mantis->num); return -EREMOTEIO; @@ -81,7 +81,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - data = mmread(MANTIS_GPIF_HIFDIN); + data = mmread(MANTIS_GPIF_DIN); return (data >> 24) & 0xff; } @@ -100,8 +100,8 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); - mmwrite(data, MANTIS_GPIF_HIFDOUT); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_MEMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -124,7 +124,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); ca->hif_job_queue = MANTIS_HIF_IOMRD; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -134,9 +134,9 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) } udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; - data = mmread(MANTIS_GPIF_HIFDIN); + data = mmread(MANTIS_GPIF_DIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); return data; } @@ -152,8 +152,8 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); - mmwrite(data, MANTIS_GPIF_HIFDOUT); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_IOMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -164,7 +164,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_HIFADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); return 0; } -- cgit v1.2.3 From ea30d81a9634cb4c13bbef46877f0d7730c57552 Mon Sep 17 00:00:00 2001 From: Magnus Horlin Date: Fri, 4 Dec 2009 05:14:34 -0300 Subject: V4L/DVB (13748): [Mantis/VP-2040] Add support for VP-2040 (TDA10023 frontend based) Signed-off-by: Magnus Horlin Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_vp2040.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index a164bb14363..b94d0515de4 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -119,6 +119,7 @@ static void mantis_load_config(struct mantis_pci *mantis) case MANTIS_VP_2033_DVB_C: // VP-2033 mantis->hwconfig = &vp2033_mantis_config; break; + case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: // VP-2040 clone mantis->hwconfig = &vp2040_mantis_config; break; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index ade444963c8..3940aed8af8 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -273,6 +273,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; + case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index 825ccbb87ad..69463cc4ccc 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -25,6 +25,7 @@ #include "mantis_common.h" #include "tda1002x.h" +#define MANTIS_VP_2040_DVB_C 0x0043 #define TERRATEC_CINERGY_C_PCI 0x1178 extern struct tda1002x_config tda10023_cu1216_config; -- cgit v1.2.3 From ac23f4c86c3c901f95d72fc2262b22e6230d4feb Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:15:10 -0300 Subject: V4L/DVB (13749): [Mantis CA] CA_SLAVE: Do not change Slave Configuration setup (Need to sanitize this cleanly for different Slaves) Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 9e058be8726..d18fe415244 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -171,9 +171,11 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) int mantis_hif_init(struct mantis_ca *ca) { + struct mantis_slot *slot = ca->slot; struct mantis_pci *mantis = ca->ca_priv; u32 irqcfg; + slot[0].slave_cfg = 0x70773028; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); init_waitqueue_head(&ca->hif_data_wq); init_waitqueue_head(&ca->hif_opdone_wq); -- cgit v1.2.3 From 4d5a28efda3ce12529e4b90832184f62c7a50848 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:15:38 -0300 Subject: V4L/DVB (13750): [Mantis] GPIO_CONTROL: Cache a given GPIO Bit Setup for a given event Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_core.c | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 0aa4001dea9..75f07736e00 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -137,7 +137,7 @@ struct mantis_pci { u32 sub_device_id; /* A12 A13 A14 */ - int gpio_status; + u32 gpio_status; struct mantis_ca *mantis_ca; }; diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index b94d0515de4..3fd3b0801cf 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -185,16 +185,15 @@ int mantis_core_exit(struct mantis_pci *mantis) // Turn the given bit on or off. void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { - u32 currVal, newVal; - - currVal = mmread(MANTIS_GPIF_ADDR); + u32 cur; + cur = mmread(MANTIS_GPIF_ADDR); if (value) - newVal = currVal | (1 << bitpos); + mantis->gpio_status = cur | (1 << bitpos); else - newVal = currVal & (~(1 << bitpos)); + mantis->gpio_status = cur & (~(1 << bitpos)); - mmwrite(newVal, MANTIS_GPIF_ADDR); + mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); udelay(100); } -- cgit v1.2.3 From b2d8f5eafd31cd7bc722dc93057d8c5fd5b688ab Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:16:24 -0300 Subject: V4L/DVB (13751): [Mantis] GPIO_CONTROL: Do not toggle GPIO CW's on HIF operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_hif.c | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 75f07736e00..49f2f118b49 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -142,6 +142,8 @@ struct mantis_pci { struct mantis_ca *mantis_ca; }; +#define MANTIS_HIF_STATUS (mantis->gpio_status << 12) + extern unsigned int verbose; extern unsigned int devs; extern unsigned int i2c; diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index d18fe415244..96611b67cb4 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -56,6 +56,7 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) return rc; } + int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) { struct mantis_pci *mantis = ca->ca_priv; @@ -67,7 +68,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_BRADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); mmwrite(count, MANTIS_GPIF_BRBYTES); udelay(20); @@ -100,7 +101,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_MEMWR; @@ -124,7 +125,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); ca->hif_job_queue = MANTIS_HIF_IOMRD; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { @@ -152,7 +153,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); ca->hif_job_queue = MANTIS_HIF_IOMWR; -- cgit v1.2.3 From b619f9f8a111be3f6ec8ec2671eb93c66a673b90 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:17:14 -0300 Subject: V4L/DVB (13752): [Mantis CA] CAM_CONTROL: All CAM control operations now handled by the worker thread Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 6eecd54a445..4873fa9586e 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -183,20 +183,7 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, mantis->subsystem_device = pdev->subsystem_device; init_waitqueue_head(&mantis->i2c_wq); - // CAM bypass - //mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ1, MANTIS_INT_MASK); - dprintk(verbose, MANTIS_INFO, 0, "\ngpif status: %04x irqcfg: %04x\n", mmread(0x9c), mmread(0x98)); - if ((mmread(0x9c) & 0x200) != 0) { //CAM inserted - msleep_interruptible(1); - if ((mmread(0x9c) & 0x200) != 0) - mmwrite(((mmread(0x98) | 0x01) & ~0x02), 0x98); - else - mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); - - } else { - mmwrite(((mmread(0x98) | 0x02) & ~0x01), 0x98); - } - mantis_set_direction(mantis, 0); + mantis_set_direction(mantis, 0); /* CAM bypass */ if (!latency) pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); -- cgit v1.2.3 From fb6de9c5fe13fd5cd866c49204e6bd91d73f83b0 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:17:46 -0300 Subject: V4L/DVB (13753): [Mantis CA] SLOT_CONTROL: Implement Slot RESET Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index f6d70cb3f6f..a30eb844ffd 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -80,6 +80,11 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); + udelay(500); /* Wait.. */ + mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */ + udelay(500); + mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */ + msleep(1000); return 0; } -- cgit v1.2.3 From 990f8d1e161429ee1a0e9708f7989543e4648f73 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:18:27 -0300 Subject: V4L/DVB (13754): [Mantis] CAM_CONTROL: Implement TS control Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 1 + drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_core.h | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index a30eb844ffd..b9d808bf710 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -105,6 +105,7 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) struct mantis_pci *mantis = ca->ca_priv; dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); + mantis_set_direction(mantis, 1); /* Enable TS through CAM */ return 0; } diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 49f2f118b49..ac3eefec0a7 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -153,6 +153,8 @@ extern int mantis_dvb_exit(struct mantis_pci *mantis); extern void mantis_dma_xfer(unsigned long data); extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); +extern void mantis_set_direction(struct mantis_pci *mantis, int direction); + extern int mantis_ca_init(struct mantis_pci *mantis); extern void mantis_ca_exit(struct mantis_pci *mantis); diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h index 31b2a756d99..a8093940993 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -53,9 +53,5 @@ extern int mantis_i2c_init(struct mantis_pci *mantis); extern int mantis_i2c_exit(struct mantis_pci *mantis); extern int mantis_core_init(struct mantis_pci *mantis); extern int mantis_core_exit(struct mantis_pci *mantis); -//extern void mantis_fe_powerup(struct mantis_pci *mantis); -//extern void mantis_fe_powerdown(struct mantis_pci *mantis); -//extern void mantis_fe_reset(struct dvb_frontend *fe); -extern void mantis_set_direction(struct mantis_pci *mantis, int direction); #endif //__MANTIS_CORE_H -- cgit v1.2.3 From f9ce1c3f32aa472c667c4d43d01c42922fb356ca Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:18:53 -0300 Subject: V4L/DVB (13755): [Mantis CA] CAM_CONTROL: Use appropriate flags Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index b9d808bf710..2c49f6bae49 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -138,6 +138,9 @@ int mantis_ca_init(struct mantis_pci *mantis) ca->ca_priv = mantis; mantis->mantis_ca = ca; + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | + DVB_CA_EN50221_FLAG_IRQ_FR | + DVB_CA_EN50221_FLAG_IRQ_DA; /* register CA interface */ ca->en50221.owner = THIS_MODULE; -- cgit v1.2.3 From 05691cdbf479282e3d3c2e3386cb865cbf611e3a Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:19:26 -0300 Subject: V4L/DVB (13756): [Mantis CA] CAM_CONTROL: Use CAMCHANGE_IRQ events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index dbcdca3a8f0..79c3c625e2e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -39,12 +39,18 @@ static void mantis_hifevm_work(struct work_struct *work) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_plugin(ca); + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_unplug(ca); + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_REMOVED); } } -- cgit v1.2.3 From bb928a7a21273f67455912f0935ff943ddb35d0c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:20:14 -0300 Subject: V4L/DVB (13757): [Mantis CA] CAM_CONTROL: Use FRDA_IRQ Events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 79c3c625e2e..ee049555a3c 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -69,8 +69,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; - if (ca->hif_job_queue & MANTIS_HIF_MEMRD) - wake_up(&ca->hif_brrdyw_wq); + dvb_ca_en50221_frda_irq(&ca->en50221, 0); } if (gpif_stat & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); -- cgit v1.2.3 From 2ec9b00bd0386b71c8a84a3990a13ea9656fe8dd Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:20:44 -0300 Subject: V4L/DVB (13758): [Mantis CA] CAM_CONTROL: Use CAMREADY_IRQ event Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 1 + drivers/media/dvb/mantis/mantis_evm.c | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 2c49f6bae49..abd8855cabf 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -85,6 +85,7 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) udelay(500); mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */ msleep(1000); + dvb_ca_en50221_camready_irq(&ca->en50221, 0); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index ee049555a3c..469571508d1 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -82,10 +82,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); - if (ca->hif_job_queue) { - wake_up(&ca->hif_opdone_wq); - ca->hif_event = MANTIS_SBUF_OPDONE; - } + } } -- cgit v1.2.3 From 9c8679554db8cf39ccec5a90cfaa12b164585556 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:21:05 -0300 Subject: V4L/DVB (13759): [Mantis] HIF I/O: Use the LSB octet only Thanks to Abylai Ospan for pointing this out. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 96611b67cb4..1ccd8696953 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -139,7 +139,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); - return data; + return (u8) data; } int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) -- cgit v1.2.3 From 86c75c5c2b9318f4b3218615ada18badabd3f166 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:21:27 -0300 Subject: V4L/DVB (13760): [Mantis CA] CA_MODULE: Look for module status on driver load Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pcmcia.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 47cc720d35d..59f1a06f0d9 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -83,6 +83,9 @@ int mantis_pcmcia_init(struct mantis_ca *ca) dprintk(verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_INSERTED; + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_INSERTED); } else { dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); -- cgit v1.2.3 From cc0e4aacaf4c3660fa759ce1299377baaf9efd8b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:21:51 -0300 Subject: V4L/DVB (13761): [Mantis] HIF I/O: Temporary workaround, use SBUF_OPDONE flag instead Dnumgis got hit with this bug, using a temporary workaround for the time being rather than digging deep at this point. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 469571508d1..532bcfff5ae 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -68,8 +68,6 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; - dvb_ca_en50221_frda_irq(&ca->en50221, 0); } if (gpif_stat & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); @@ -82,7 +80,8 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); - + ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; + dvb_ca_en50221_frda_irq(&ca->en50221, 0); } } -- cgit v1.2.3 From 88a6fa9dfec0a585409acbb49a7f86a933b35d2b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:22:33 -0300 Subject: V4L/DVB (13762): [Mantis CA] CA_MODULE: Look for the module status on driver unload as well Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pcmcia.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 59f1a06f0d9..4156a082088 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -90,6 +90,9 @@ int mantis_pcmcia_init(struct mantis_ca *ca) dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_XTRACTED; + dvb_ca_en50221_camchange_irq(&ca->en50221, + 0, + DVB_CA_EN50221_CAMCHANGE_REMOVED); } return 0; -- cgit v1.2.3 From 8e0d58ecee2abc12f298862b7f9a90d1593e8006 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:22:57 -0300 Subject: V4L/DVB (13763): [Mantis] HIF I/O: trim delays a bit appropriately Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 1ccd8696953..880b99634c2 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -133,11 +133,11 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; data = mmread(MANTIS_GPIF_DIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + udelay(50); return (u8) data; } @@ -162,10 +162,10 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - udelay(50); ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + udelay(50); return 0; } -- cgit v1.2.3 From 5e2a0c99019bbc78d6fb00caf7a79f03df020b3c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:23:17 -0300 Subject: V4L/DVB (13764): [Mantis CA] SLOT: Add some debug status Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index abd8855cabf..b79a89276e3 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -118,8 +118,12 @@ static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); - if (ca->slot_state == MODULE_INSERTED) + if (ca->slot_state == MODULE_INSERTED) { + dprintk(verbose, MANTIS_DEBUG, 1, "CA Module present and ready"); return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } else { + dprintk(verbose, MANTIS_DEBUG, 1, "CA Module not present or not ready"); + } return 0; } -- cgit v1.2.3 From 8b9c385f765bcc7fc5ae802830ffcb4b6ca6bc9c Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:23:38 -0300 Subject: V4L/DVB (13765): [Mantis] HIF I/O: Add some debug statements Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 880b99634c2..c2cecc3d7b1 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -51,6 +51,7 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); rc = -EREMOTEIO; } + dprintk(verbose, MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); ca->hif_event &= ~MANTIS_SBUF_OPDONE; udelay(5); return rc; @@ -83,7 +84,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); - + dprintk(verbose, MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); return (data >> 24) & 0xff; } @@ -111,6 +112,8 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) return -EREMOTEIO; } ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; + dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); + return 0; } @@ -137,6 +140,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) data = mmread(MANTIS_GPIF_DIN); hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); return (u8) data; @@ -165,6 +169,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; hif_addr |= MANTIS_GPIF_PCMCIAREG; mmwrite(hif_addr, MANTIS_GPIF_ADDR); + dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); udelay(50); return 0; -- cgit v1.2.3 From b29453aca0eeecba52a76c3d67b1a52c3ca6e656 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:24:01 -0300 Subject: V4L/DVB (13766): [Mantis] Bug: Fix wrong exit condition Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 532bcfff5ae..214ae5ee31e 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -31,8 +31,6 @@ static void mantis_hifevm_work(struct work_struct *work) gpif_stat = mmread(MANTIS_GPIF_STATUS); gpif_mask = mmread(MANTIS_GPIF_IRQCFG); - if (!((gpif_stat & 0xff) & (gpif_mask & 0xff))) - return; if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { -- cgit v1.2.3 From 18b6de42d77e7762be929a4a858c359de352e1e2 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:24:47 -0300 Subject: V4L/DVB (13767): [Mantis/VP-1041] Bug: Add in missing Master clock settings Thanks to Ershov and Igor for pointing it out. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_vp1041.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 7dee1af0d64..8eb1afdab11 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -267,6 +267,9 @@ struct stb0899_config vp1041_config = { .xtal_freq = 27000000, .inversion = IQ_SWAP_ON, /* 1 */ + .lo_clk = 76500000, + .hi_clk = 99000000, + .esno_ave = STB0899_DVBS2_ESNO_AVE, .esno_quant = STB0899_DVBS2_ESNO_QUANT, .avframes_coarse = STB0899_DVBS2_AVFRAMES_COARSE, -- cgit v1.2.3 From adcc9dd57e814d5ac3928f92f431fbe4808e936f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:25:18 -0300 Subject: V4L/DVB (13768): [Mantis] Enable WRACK Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 10 +++++++++- drivers/media/dvb/mantis/mantis_hif.c | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 214ae5ee31e..000cf396a2c 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -27,11 +27,19 @@ static void mantis_hifevm_work(struct work_struct *work) struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); struct mantis_pci *mantis = ca->ca_priv; - u32 gpif_stat, gpif_mask; + u32 gpif_stat, gpif_mask, rst_mask, rst_stat; + + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; gpif_stat = mmread(MANTIS_GPIF_STATUS); gpif_mask = mmread(MANTIS_GPIF_IRQCFG); + rst_stat = gpif_stat & rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index c2cecc3d7b1..2f1a6cb943d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -188,6 +188,7 @@ int mantis_hif_init(struct mantis_ca *ca) irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg |= MANTIS_MASK_BRRDY; + irqcfg |= MANTIS_MASK_WRACK; mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); return 0; -- cgit v1.2.3 From 9e49e8d913209e7221f761193f18a91d130b9e2d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:25:45 -0300 Subject: V4L/DVB (13769): [Mantis] Smart Buffer Burst Read Ready cannot flag FR/DA Irq Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 000cf396a2c..1594bb85a20 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -72,9 +72,9 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OVFLW) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); - if (gpif_stat & MANTIS_GPIF_BRRDY) { + if (gpif_stat & MANTIS_GPIF_BRRDY) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - } + if (gpif_stat & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); -- cgit v1.2.3 From f668c7292bda7f64400eaa8d45c3a785eecab990 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:26:18 -0300 Subject: V4L/DVB (13770): [Mantis] Bug Do not trigger FR/DA IRQ from SBUF OPDONE Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 1594bb85a20..d603601c09b 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -87,7 +87,6 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; - dvb_ca_en50221_frda_irq(&ca->en50221, 0); } } -- cgit v1.2.3 From 17b77fc2d404910ca691661038ceb4c02d912d16 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:26:46 -0300 Subject: V4L/DVB (13771): [Mantis] Reset Flags at the earliest possible Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 ++ drivers/media/dvb/mantis/mantis_evm.c | 18 +++++------------- drivers/media/dvb/mantis/mantis_pci.c | 12 ++++++++++++ 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index ac3eefec0a7..27ecfdb6e6f 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -139,6 +139,8 @@ struct mantis_pci { /* A12 A13 A14 */ u32 gpio_status; + u32 gpif_status; + struct mantis_ca *mantis_ca; }; diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index d603601c09b..4c4c1448ddd 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -27,19 +27,11 @@ static void mantis_hifevm_work(struct work_struct *work) struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work); struct mantis_pci *mantis = ca->ca_priv; - u32 gpif_stat, gpif_mask, rst_mask, rst_stat; - - rst_mask = MANTIS_GPIF_WRACK | - MANTIS_GPIF_OTHERR | - MANTIS_SBUF_WSTO | - MANTIS_GPIF_EXTIRQ; + u32 gpif_stat, gpif_mask; gpif_stat = mmread(MANTIS_GPIF_STATUS); gpif_mask = mmread(MANTIS_GPIF_IRQCFG); - rst_stat = gpif_stat & rst_mask; - mmwrite(rst_stat, MANTIS_GPIF_STATUS); - if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); @@ -60,13 +52,13 @@ static void mantis_hifevm_work(struct work_struct *work) } } - if (gpif_stat & MANTIS_GPIF_EXTIRQ) + if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); - if (gpif_stat & MANTIS_SBUF_WSTO) + if (mantis->gpif_status & MANTIS_SBUF_WSTO) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); - if (gpif_stat & MANTIS_GPIF_OTHERR) + if (mantis->gpif_status & MANTIS_GPIF_OTHERR) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); if (gpif_stat & MANTIS_SBUF_OVFLW) @@ -75,7 +67,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - if (gpif_stat & MANTIS_GPIF_WRACK) + if (mantis->gpif_status & MANTIS_GPIF_WRACK) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); if (gpif_stat & MANTIS_GPIF_INTSTAT) diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 4873fa9586e..f57e2a43b9e 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -53,6 +53,8 @@ MODULE_DEVICE_TABLE(pci, mantis_pci_table); static irqreturn_t mantis_pci_irq(int irq, void *dev_id) { u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + u32 rst_stat = 0, rst_mask = 0; + struct mantis_pci *mantis; struct mantis_ca *ca; @@ -69,6 +71,15 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) if (!(stat & mask)) return IRQ_NONE; + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; + + rst_stat = mmread(MANTIS_GPIF_STATUS); + rst_stat &= rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + mantis->mantis_int_stat = stat; mantis->mantis_int_mask = mask; dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); @@ -77,6 +88,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); + mantis->gpif_status = rst_stat; schedule_work(&ca->hif_evm_work); } if (stat & MANTIS_INT_IRQ1) { -- cgit v1.2.3 From 578413228ae72a09b29bf29e879e5b919ded0ac4 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:27:26 -0300 Subject: V4L/DVB (13772): [Mantis] Do not enable Common Memory Access Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 2f1a6cb943d..151de2d687e 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -138,8 +138,6 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) } ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; data = mmread(MANTIS_GPIF_DIN); - hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); @@ -167,8 +165,6 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) return -EREMOTEIO; } ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; - hif_addr |= MANTIS_GPIF_PCMCIAREG; - mmwrite(hif_addr, MANTIS_GPIF_ADDR); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); udelay(50); -- cgit v1.2.3 From c90d345fd7d66899d743611a47163f9904df90bc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:27:53 -0300 Subject: V4L/DVB (13773): [Mantis] Enable all interrupts Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 151de2d687e..fa4bb6dc324 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -182,9 +182,14 @@ int mantis_hif_init(struct mantis_ca *ca) init_waitqueue_head(&ca->hif_data_wq); init_waitqueue_head(&ca->hif_opdone_wq); - irqcfg = mmread(MANTIS_GPIF_IRQCFG); - irqcfg |= MANTIS_MASK_BRRDY; - irqcfg |= MANTIS_MASK_WRACK; + irqcfg = mmread(MANTIS_GPIF_IRQCFG); + irqcfg = MANTIS_MASK_BRRDY | + MANTIS_MASK_WRACK | + MANTIS_MASK_EXTIRQ | + MANTIS_MASK_WSTO | + MANTIS_MASK_OTHERR | + MANTIS_MASK_OVFLW; + mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); return 0; -- cgit v1.2.3 From c02e15150c85619f22a98675124503ed93bf1914 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:28:24 -0300 Subject: V4L/DVB (13774): [Mantis] Remove redundant wait for Burst Reads, wakeup the HIF event Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 2 ++ drivers/media/dvb/mantis/mantis_hif.c | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 4c4c1448ddd..008e2c28c06 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -79,6 +79,8 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_SBUF_OPDONE) { dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; + ca->hif_event = MANTIS_SBUF_OPDONE; + wake_up(&ca->hif_opdone_wq); } } diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index fa4bb6dc324..6c51d178001 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -75,10 +75,6 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) udelay(20); mmwrite(hif_addr, MANTIS_GPIF_ADDR); - if (mantis_hif_data_available(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer burst read failed", mantis->num); - return -EREMOTEIO; - } if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; -- cgit v1.2.3 From b9fd5877463605b91743552b4989666792bf4fbc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:29:03 -0300 Subject: V4L/DVB (13775): [Mantis] Remove unnecessary job queues Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 10 ---------- drivers/media/dvb/mantis/mantis_link.h | 1 - 2 files changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 6c51d178001..621dce3eb5d 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -97,17 +97,13 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) hif_addr |= addr; mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - ca->hif_job_queue = MANTIS_HIF_MEMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - ca->hif_job_queue &= ~MANTIS_HIF_MEMWR; dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); return 0; @@ -125,14 +121,11 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= addr; mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); - ca->hif_job_queue = MANTIS_HIF_IOMRD; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - ca->hif_job_queue &= ~MANTIS_HIF_IOMRD; data = mmread(MANTIS_GPIF_DIN); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); @@ -154,13 +147,10 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - ca->hif_job_queue = MANTIS_HIF_IOMWR; if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } - ca->hif_job_queue &= ~MANTIS_HIF_IOMWR; dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); udelay(50); diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 23ff2d6aadb..a85f5021526 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -51,7 +51,6 @@ struct mantis_ca { wait_queue_head_t hif_opdone_wq; wait_queue_head_t hif_brrdyw_wq; wait_queue_head_t hif_data_wq; - u32 hif_job_queue; enum mantis_sbuf_status sbuf_status; -- cgit v1.2.3 From ac8f04d2723b3de7c36430d67401ce89c858e117 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:29:25 -0300 Subject: V4L/DVB (13776): [Mantis] Use a simple timeout instead, interruptible timeouts sleep unnecessarily too long Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 621dce3eb5d..a2359f7e146 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -44,9 +44,9 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; int rc = 0; - if (wait_event_interruptible_timeout(ca->hif_opdone_wq, - ca->hif_event & MANTIS_SBUF_OPDONE, - msecs_to_jiffies(500)) == -ERESTARTSYS) { + if (wait_event_timeout(ca->hif_opdone_wq, + ca->hif_event & MANTIS_SBUF_OPDONE, + msecs_to_jiffies(500)) == -ERESTARTSYS) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); rc = -EREMOTEIO; -- cgit v1.2.3 From e0e099a708043a2341d8987014ce4ba98a4dbd30 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:29:48 -0300 Subject: V4L/DVB (13777): [Mantis] Use a Write wait queue for Write events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 34 ++++++++++++++++++++++++++++++++-- drivers/media/dvb/mantis/mantis_link.h | 1 + 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index a2359f7e146..dc50fac0d15 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -57,6 +57,35 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) return rc; } +static int mantis_hif_write_wait(struct mantis_ca *ca) +{ + struct mantis_pci *mantis = ca->ca_priv; + u32 opdone = 0, timeout = 0; + int rc = 0; + + if (wait_event_timeout(ca->hif_write_wq, + mantis->gpif_status & MANTIS_GPIF_WRACK, + msecs_to_jiffies(500)) == -ERESTARTSYS) { + + dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); + rc = -EREMOTEIO; + } + dprintk(verbose, MANTIS_DEBUG, 1, "Write Acknowledged"); + mantis->gpif_status &= ~MANTIS_GPIF_WRACK; + while (!opdone) { + opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE); + udelay(500); + timeout++; + if (timeout > 100) { + dprintk(verbose, MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); + rc = -ETIMEDOUT; + break; + } + } + dprintk(verbose, MANTIS_DEBUG, 1, "HIF Write success"); + return rc; +} + int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) { @@ -100,7 +129,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } @@ -147,7 +176,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); - if (mantis_hif_sbuf_opdone_wait(ca) != 0) { + if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; } @@ -167,6 +196,7 @@ int mantis_hif_init(struct mantis_ca *ca) dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); init_waitqueue_head(&ca->hif_data_wq); init_waitqueue_head(&ca->hif_opdone_wq); + init_waitqueue_head(&ca->hif_write_wq); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg = MANTIS_MASK_BRRDY | diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index a85f5021526..599ff1b57e4 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -51,6 +51,7 @@ struct mantis_ca { wait_queue_head_t hif_opdone_wq; wait_queue_head_t hif_brrdyw_wq; wait_queue_head_t hif_data_wq; + wait_queue_head_t hif_write_wq; /* HIF Write op */ enum mantis_sbuf_status sbuf_status; -- cgit v1.2.3 From 4d019faf48ff03b6ff3463d8e5da54d61f153623 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:30:11 -0300 Subject: V4L/DVB (13778): [Mantis] Wr ACK is already handled in the fast path, do not use the event manager to handle the fast events Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_evm.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 008e2c28c06..9be55f7942d 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -67,9 +67,6 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_BRRDY) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); - if (mantis->gpif_status & MANTIS_GPIF_WRACK) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Slave Write ACK", mantis->num); - if (gpif_stat & MANTIS_GPIF_INTSTAT) dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); -- cgit v1.2.3 From 25e9eba42ce11a05933068cf6a42dd8d4ed5edb8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:30:33 -0300 Subject: V4L/DVB (13779): [Mantis] Missing wakeup for write queue Thanks to Sigmund for pointing it out Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index f57e2a43b9e..a068ffb3253 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -89,6 +89,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) if (stat & MANTIS_INT_IRQ0) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); mantis->gpif_status = rst_stat; + wake_up(&ca->hif_write_wq); schedule_work(&ca->hif_evm_work); } if (stat & MANTIS_INT_IRQ1) { -- cgit v1.2.3 From c63e507346c042af7fe26d49bbbdce9898ea3eea Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Fri, 4 Dec 2009 05:30:59 -0300 Subject: V4L/DVB (13780): [Mantis] HIF I/O: Enable Interrupts for Read Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index dc50fac0d15..323d1fb0a55 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -149,6 +149,11 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= addr; + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); + mmwrite(1, MANTIS_GPIF_BRBYTES); + + udelay(20); + mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { -- cgit v1.2.3 From b29f6ac248e49d8425aa91afb1b53d1f6d47ebe3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:31:21 -0300 Subject: V4L/DVB (13781): [Mantis CA] Bug: Fix wrong usage of HIFRDWRN Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 323d1fb0a55..3368253aea6 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -53,7 +53,6 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) } dprintk(verbose, MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); ca->hif_event &= ~MANTIS_SBUF_OPDONE; - udelay(5); return rc; } @@ -93,17 +92,16 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) u32 hif_addr = 0, data, count = 4; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); - hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; + hif_addr |= MANTIS_HIF_STATUS; hif_addr |= addr; - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); + mmwrite(hif_addr, MANTIS_GPIF_BRADDR); mmwrite(count, MANTIS_GPIF_BRBYTES); - udelay(20); + mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); - mmwrite(hif_addr, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); return -EREMOTEIO; @@ -123,10 +121,11 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; - hif_addr |= addr; + hif_addr |= MANTIS_HIF_STATUS; + hif_addr |= addr; mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */ - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { @@ -145,16 +144,14 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; - hif_addr |= MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= MANTIS_HIF_STATUS; hif_addr |= addr; - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_BRADDR); + mmwrite(hif_addr, MANTIS_GPIF_BRADDR); mmwrite(1, MANTIS_GPIF_BRBYTES); - udelay(20); - - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); + mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); @@ -176,9 +173,10 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; + hif_addr |= MANTIS_HIF_STATUS; hif_addr |= addr; - mmwrite(hif_addr | MANTIS_HIF_STATUS, MANTIS_GPIF_ADDR); + mmwrite(hif_addr, MANTIS_GPIF_ADDR); mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { -- cgit v1.2.3 From e26c2b46201e5ae38111391c293cec08870b7f6d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:31:45 -0300 Subject: V4L/DVB (13782): [Mantis] Temporarily disable FRDA irq Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index b79a89276e3..177b04813ff 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -143,10 +143,7 @@ int mantis_ca_init(struct mantis_pci *mantis) ca->ca_priv = mantis; mantis->mantis_ca = ca; - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | - DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA; - + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; /* register CA interface */ ca->en50221.owner = THIS_MODULE; ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; -- cgit v1.2.3 From f5701b67767c6b81a035c9e2b539025f91d1e84d Mon Sep 17 00:00:00 2001 From: Marko Viitamaki Date: Fri, 4 Dec 2009 05:32:30 -0300 Subject: V4L/DVB (13783): [Mantis/Technisat Cablestar HD2] Add support for the Technisat Cablestar HD2 Signed-off-by: Marko Viitamaki Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_core.c | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 1 + drivers/media/dvb/mantis/mantis_vp2040.h | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 3fd3b0801cf..c3d0d53bc38 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -121,6 +121,7 @@ static void mantis_load_config(struct mantis_pci *mantis) break; case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: // VP-2040 clone + case TECHNISAT_CABLESTAR_HD2: mantis->hwconfig = &vp2040_mantis_config; break; case MANTIS_VP_3030_DVB_T: // VP-3030 diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 3940aed8af8..c3a35bee468 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -275,6 +275,7 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) break; case MANTIS_VP_2040_DVB_C: // VP-2040 case TERRATEC_CINERGY_C_PCI: + case TECHNISAT_CABLESTAR_HD2: dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); if (mantis->fe) { diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index 69463cc4ccc..645dade7543 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -27,6 +27,7 @@ #define MANTIS_VP_2040_DVB_C 0x0043 #define TERRATEC_CINERGY_C_PCI 0x1178 +#define TECHNISAT_CABLESTAR_HD2 0x0002 extern struct tda1002x_config tda10023_cu1216_config; extern struct mantis_hwconfig vp2040_mantis_config; -- cgit v1.2.3 From ff63ac56705539e162d2f020a0c2a607eae37d7b Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:32:51 -0300 Subject: V4L/DVB (13784): [Mantis] Use PCI API instead of hardcoded length Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index a068ffb3253..d3a62b18590 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -169,7 +169,10 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, goto err0; } - if ((mantis->mantis_mmio = ioremap(mantis->mantis_addr, 0x1000)) == NULL) { + mantis->mantis_mmio = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + + if (!mantis->mantis_mmio) { dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); ret = -ENODEV; goto err1; -- cgit v1.2.3 From 13d5036ea0636e6204e1b17bd12ea25061a686be Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:33:10 -0300 Subject: V4L/DVB (13785): [Mantis] Do not disable IRQ's while being invoked Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index d3a62b18590..94abcee3fc7 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -181,8 +181,11 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, // Clear and disable all interrupts at startup // to avoid lockup situations mmwrite(0x00, MANTIS_INT_MASK); - if (request_irq(pdev->irq, mantis_pci_irq, IRQF_SHARED | IRQF_DISABLED, - DRIVER_NAME, mantis) < 0) { + if (request_irq(pdev->irq, + mantis_pci_irq, + IRQF_SHARED, + DRIVER_NAME, + mantis) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); ret = -ENODEV; -- cgit v1.2.3 From 263645de70175d8b5a5e392a1856e99e2e1b7209 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:33:31 -0300 Subject: V4L/DVB (13786): [Mantis] Bug: HIF bits already shifted .. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 27ecfdb6e6f..6b9f92b4ab3 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -144,7 +144,7 @@ struct mantis_pci { struct mantis_ca *mantis_ca; }; -#define MANTIS_HIF_STATUS (mantis->gpio_status << 12) +#define MANTIS_HIF_STATUS (mantis->gpio_status) extern unsigned int verbose; extern unsigned int devs; -- cgit v1.2.3 From 616f75e1979f5bd1f3241581c720349c2c31f6e7 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:33:56 -0300 Subject: V4L/DVB (13787): [Mantis] Fix build Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 5 ++++- drivers/media/dvb/mantis/mantis_vp1033.c | 2 +- drivers/media/dvb/mantis/mantis_vp2040.c | 2 +- drivers/media/dvb/mantis/mantis_vp2040.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index c3a35bee468..5172e856354 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -32,6 +32,8 @@ #include "mantis_vp2040.h" #include "mantis_vp3030.h" +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + /* Tuner power supply control */ void mantis_fe_powerup(struct mantis_pci *mantis) { @@ -128,7 +130,8 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); if (dvb_register_adapter(&mantis->dvb_adapter, "Mantis dvb adapter", THIS_MODULE, - &mantis->pdev->dev) < 0) { + &mantis->pdev->dev, + adapter_nr) < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); return -ENODEV; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index daf02c12d29..797c4e0c7ea 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -74,7 +74,7 @@ struct stv0299_config lgtdqcs001f_config = { .invert = 1, // .enhanced_tuning = 0, .skip_reinit = 0, - .lock_output = STV0229_LOCKOUTPUT_0, +// .lock_output = STV0229_LOCKOUTPUT_0, .volt13_op0_op1 = STV0299_VOLT13_OP0, .min_delay_ms = 100, .set_symbol_rate = lgtdqcs001f_set_symbol_rate, diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index 07da73827fd..f77be7b6491 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -30,7 +30,7 @@ struct mantis_hwconfig vp2040_mantis_config = { .ts_size = MANTIS_TS_204, }; -struct tda1002x_config tda10023_cu1216_config = { +struct tda10023_config tda10023_cu1216_config = { .demod_address = 0x18 >> 1, .invert = 1, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index 645dade7543..c7457543d8b 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -29,7 +29,7 @@ #define TERRATEC_CINERGY_C_PCI 0x1178 #define TECHNISAT_CABLESTAR_HD2 0x0002 -extern struct tda1002x_config tda10023_cu1216_config; +extern struct tda10023_config tda10023_cu1216_config; extern struct mantis_hwconfig vp2040_mantis_config; #endif //__MANTIS_VP2040_H -- cgit v1.2.3 From f684336bba673b6656cb98144130ab52dafc3240 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:34:19 -0300 Subject: V4L/DVB (13788): [Mantis CA] use a lock for the relevant CI Read/Write operations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_hif.c | 16 ++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 2 ++ 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 3368253aea6..b1e1aa0f5c1 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -92,6 +92,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) u32 hif_addr = 0, data, count = 4; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; hif_addr |= MANTIS_HIF_STATUS; @@ -104,9 +105,11 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); + mutex_unlock(&ca->ca_lock); dprintk(verbose, MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); return (data >> 24) & 0xff; } @@ -118,6 +121,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) u32 hif_addr = 0; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -130,9 +134,11 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); + mutex_unlock(&ca->ca_lock); return 0; } @@ -143,6 +149,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) u32 data, hif_addr = 0; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_PCMCIAIOM; hif_addr |= MANTIS_HIF_STATUS; @@ -155,11 +162,13 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) if (mantis_hif_sbuf_opdone_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); + mutex_unlock(&ca->ca_lock); return (u8) data; } @@ -170,6 +179,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) u32 hif_addr = 0; dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); + mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr |= MANTIS_GPIF_PCMCIAIOM; @@ -181,9 +191,11 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) if (mantis_hif_write_wait(ca) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); + mutex_unlock(&ca->ca_lock); udelay(50); return 0; @@ -201,6 +213,7 @@ int mantis_hif_init(struct mantis_ca *ca) init_waitqueue_head(&ca->hif_opdone_wq); init_waitqueue_head(&ca->hif_write_wq); + mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg = MANTIS_MASK_BRRDY | MANTIS_MASK_WRACK | @@ -210,6 +223,7 @@ int mantis_hif_init(struct mantis_ca *ca) MANTIS_MASK_OVFLW; mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); + mutex_unlock(&ca->ca_lock); return 0; } @@ -220,7 +234,9 @@ void mantis_hif_exit(struct mantis_ca *ca) u32 irqcfg; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); + mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg &= ~MANTIS_MASK_BRRDY; mmwrite(irqcfg, MANTIS_GPIF_IRQCFG); + mutex_unlock(&ca->ca_lock); } diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index 599ff1b57e4..f9aaaa52f52 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -21,6 +21,7 @@ #ifndef __MANTIS_LINK_H #define __MANTIS_LINK_H +#include #include #include "dvb_ca_en50221.h" @@ -61,6 +62,7 @@ struct mantis_ca { void *ca_priv; struct dvb_ca_en50221 en50221; + struct mutex ca_lock; }; /* CA */ -- cgit v1.2.3 From 99b55b2c4478e6370aaa85173f5090a070c50a08 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:34:44 -0300 Subject: V4L/DVB (13789): [Mantis CA] Initialize the mutex Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 177b04813ff..53c01b3023c 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -156,6 +156,8 @@ int mantis_ca_init(struct mantis_pci *mantis) ca->en50221.poll_slot_status = mantis_slot_status; ca->en50221.data = ca; + mutex_init(&ca->ca_lock); + dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); -- cgit v1.2.3 From 42f541bfd1a9bad84a288d59a98fdb284df61a45 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:35:07 -0300 Subject: V4L/DVB (13790): [Mantis] Relocate queue initialization Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ca.c | 4 ++++ drivers/media/dvb/mantis/mantis_hif.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 53c01b3023c..7aa27e0703b 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -158,6 +158,10 @@ int mantis_ca_init(struct mantis_pci *mantis) mutex_init(&ca->ca_lock); + init_waitqueue_head(&ca->hif_data_wq); + init_waitqueue_head(&ca->hif_opdone_wq); + init_waitqueue_head(&ca->hif_write_wq); + dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index b1e1aa0f5c1..99a9724cbaf 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -209,9 +209,6 @@ int mantis_hif_init(struct mantis_ca *ca) slot[0].slave_cfg = 0x70773028; dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); - init_waitqueue_head(&ca->hif_data_wq); - init_waitqueue_head(&ca->hif_opdone_wq); - init_waitqueue_head(&ca->hif_write_wq); mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); -- cgit v1.2.3 From 4af699c13a5fb7332255de5fa56442d065f547a3 Mon Sep 17 00:00:00 2001 From: Niklas Edmundsson Date: Fri, 4 Dec 2009 05:38:21 -0300 Subject: V4L/DVB (13791): [TDA10021] Do not claim TDA10023 Signed-off-by: Niklas Edmundsson Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10021.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 6c1dbf9288d..6ca533ea0f0 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -426,6 +426,10 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config, id = tda10021_readreg(state, 0x1a); if ((id & 0xf0) != 0x70) goto error; + /* Don't claim TDA10023 */ + if (id == 0x7d) + goto error; + printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n", state->config->demod_address, id); -- cgit v1.2.3 From ec1b6ff1cce9d406a9a5f84a1d1205328f2c515a Mon Sep 17 00:00:00 2001 From: Niklas Edmundsson Date: Fri, 4 Dec 2009 05:38:52 -0300 Subject: V4L/DVB (13792): [Mantis/VP-2033] Do not claim TDA10023 Do not rely on the PCI ID alone Signed-off-by: Niklas Edmundsson Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 5172e856354..de18bb97d8e 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -263,30 +263,31 @@ int __devinit mantis_frontend_init(struct mantis_pci *mantis) } break; case MANTIS_VP_2033_DVB_C: // VP-2033 + case MANTIS_VP_2040_DVB_C: // VP-2040 + case TERRATEC_CINERGY_C_PCI: + case TECHNISAT_CABLESTAR_HD2: dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10021_attach(&philips_cu1216_config, &mantis->adapter, read_pwm(mantis)); + mantis->fe = tda10021_attach(&philips_cu1216_config, + &mantis->adapter, + read_pwm(mantis)); + if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; dprintk(verbose, MANTIS_ERROR, 1, "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", philips_cu1216_config.demod_address); - - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-C Philips CU1216 frontend attach success"); - + } else { + mantis->fe = tda10023_attach(&tda10023_cu1216_config, + &mantis->adapter, + read_pwm(mantis)); + + if (mantis->fe) { + dprintk(verbose, MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + philips_cu1216_config.demod_address); + } } - break; - case MANTIS_VP_2040_DVB_C: // VP-2040 - case TERRATEC_CINERGY_C_PCI: - case TECHNISAT_CABLESTAR_HD2: - dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10023_attach(&tda10023_cu1216_config, &mantis->adapter, read_pwm(mantis)); if (mantis->fe) { mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", - philips_cu1216_config.demod_address); - dprintk(verbose, MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); } -- cgit v1.2.3 From add206368462434ba97e8fe4de98e5d47ffdb0a0 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:39:57 -0300 Subject: V4L/DVB (13794): [Mantis/VP-3028] Initial go at Serial interface implementation, add support for VP-3028 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 2 + drivers/media/dvb/mantis/mantis_common.h | 10 +++ drivers/media/dvb/mantis/mantis_core.c | 8 ++ drivers/media/dvb/mantis/mantis_pci.c | 2 + drivers/media/dvb/mantis/mantis_uart.c | 139 +++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_uart.h | 25 +++++- drivers/media/dvb/mantis/mantis_vp1033.c | 3 + drivers/media/dvb/mantis/mantis_vp1034.c | 3 + drivers/media/dvb/mantis/mantis_vp1041.c | 3 + drivers/media/dvb/mantis/mantis_vp2033.c | 3 + drivers/media/dvb/mantis/mantis_vp2040.c | 3 + drivers/media/dvb/mantis/mantis_vp3028.c | 38 +++++++++ drivers/media/dvb/mantis/mantis_vp3028.h | 13 +++ drivers/media/dvb/mantis/mantis_vp3030.c | 3 + 14 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_uart.c create mode 100644 drivers/media/dvb/mantis/mantis_vp3028.c create mode 100644 drivers/media/dvb/mantis/mantis_vp3028.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index d002ef9f744..bb88cdc98ce 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,4 +1,5 @@ mantis-objs = mantis_core.o \ + mantis_uart.o \ mantis_dma.o \ mantis_pci.o \ mantis_i2c.o \ @@ -12,6 +13,7 @@ mantis-objs = mantis_core.o \ mantis_vp1041.o \ mantis_vp2033.o \ mantis_vp2040.o \ + mantis_vp3028.o \ mantis_vp3030.o obj-$(CONFIG_DVB_MANTIS) += mantis.o diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 6b9f92b4ab3..6a02adf1ab4 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "dvbdev.h" #include "dvb_demux.h" @@ -34,6 +35,7 @@ #include "dvb_net.h" #include #include "mantis_reg.h" +#include "mantis_uart.h" #include "mantis_link.h" @@ -74,6 +76,10 @@ struct mantis_hwconfig { char *model_name; char *dev_type; u32 ts_size; + + enum mantis_baud baud_rate; + enum mantis_parity parity; + u32 bytes; }; struct mantis_pci { @@ -142,6 +148,10 @@ struct mantis_pci { u32 gpif_status; struct mantis_ca *mantis_ca; + + wait_queue_head_t uart_wq; + struct work_struct uart_work; + spinlock_t uart_lock; }; #define MANTIS_HIF_STATUS (mantis->gpio_status) diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index c3d0d53bc38..52b3e9ebfcf 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -165,6 +165,10 @@ int mantis_core_init(struct mantis_pci *mantis) dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); return err; } + if ((err = mantis_uart_init(mantis)) < 0) { + dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed"); + return err; + } return 0; } @@ -173,6 +177,10 @@ int mantis_core_exit(struct mantis_pci *mantis) { mantis_dma_stop(mantis); dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping"); + + mantis_uart_exit(mantis); + dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed"); + if (mantis_dma_exit(mantis) < 0) dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); if (mantis_dvb_exit(mantis) < 0) diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 94abcee3fc7..d1eac4083fc 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -27,6 +27,7 @@ #include #include "mantis_common.h" #include "mantis_core.h" +#include "mantis_uart.h" #include #include @@ -94,6 +95,7 @@ static irqreturn_t mantis_pci_irq(int irq, void *dev_id) } if (stat & MANTIS_INT_IRQ1) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); + schedule_work(&mantis->uart_work); } if (stat & MANTIS_INT_OCERR) { dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c new file mode 100644 index 00000000000..786fcc33911 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -0,0 +1,139 @@ +#include +#include "mantis_common.h" + +struct mantis_uart_params { + enum mantis_baud baud_rate; + enum mantis_parity parity; +}; + +#define UART_MAX_BUF 16 + +int mantis_uart_read(struct mantis_pci *mantis, u8 *data) +{ + struct mantis_hwconfig *config = mantis->hwconfig; + u32 stat, i; + unsigned long flags; + + /* get data */ + for (i = 0; i < (config->bytes + 1); i++) { + + if (stat & MANTIS_UART_RXFIFO_FULL) { + dprintk(verbose, MANTIS_ERROR, 1, "RX Fifo FULL"); + } + data[i] = mmread(MANTIS_UART_RXD) & 0x3f; + + stat = mmread(MANTIS_UART_STAT); + + dprintk(verbose, MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); + + if (data[i] & (1 << 7)) { + dprintk(verbose, MANTIS_ERROR, 1, "UART framing error"); + return -EINVAL; + } + if (data[i] & (1 << 6)) { + dprintk(verbose, MANTIS_ERROR, 1, "UART parity error"); + return -EINVAL; + } + } + + return 0; +} + +static void mantis_uart_work(struct work_struct *work) +{ + struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work); + struct mantis_hwconfig *config = mantis->hwconfig; + u8 buf[16]; + int i; + + dprintk(verbose, MANTIS_DEBUG, 1, "UART read"); + mantis_uart_read(mantis, buf); + + dprintk(verbose, MANTIS_DEBUG, 1, "UART: "); + for (i = 0; i < (config->bytes + 1); i++) + dprintk(verbose, MANTIS_DEBUG, 0, "<%02x> ", buf[i]); + + dprintk(verbose, MANTIS_DEBUG, 0, "\n"); +} + +static int mantis_uart_setup(struct mantis_pci *mantis, + struct mantis_uart_params *params) +{ + char* rates[] = { "B_9600", "B_19200", "B_38400", "B_57600", "B_115200" }; + char* parity[] = { "NONE", "ODD", "EVEN" }; + + u32 reg; + + dprintk(verbose, MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", + parity[params->parity], + rates[params->baud_rate]); + + mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL); + + reg = mmread(MANTIS_UART_BAUD); + + switch (params->baud_rate) { + case MANTIS_BAUD_9600: + reg |= 0xd8; + break; + case MANTIS_BAUD_19200: + reg |= 0x6c; + break; + case MANTIS_BAUD_38400: + reg |= 0x36; + break; + case MANTIS_BAUD_57600: + reg |= 0x23; + break; + case MANTIS_BAUD_115200: + reg |= 0x11; + break; + default: + return -EINVAL; + } + + mmwrite(reg, MANTIS_UART_BAUD); + + return 0; +} + +int mantis_uart_init(struct mantis_pci *mantis) +{ + struct mantis_hwconfig *config = mantis->hwconfig; + struct mantis_uart_params params; + + dprintk(verbose, MANTIS_DEBUG, 1, "Initializing UART .."); + /* default parity: */ + params.baud_rate = config->baud_rate; + params.parity = config->parity; + + init_waitqueue_head(&mantis->uart_wq); + spin_lock_init(&mantis->uart_lock); + + INIT_WORK(&mantis->uart_work, mantis_uart_work); + + /* disable interrupt */ + mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); + + mantis_uart_setup(mantis, ¶ms); + + /* default 1 byte */ + mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD); + + /* flush buffer */ + mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL); + + /* enable interrupt */ + mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK); + mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); + + schedule_work(&mantis->uart_work); + + return 0; +} + +void mantis_uart_exit(struct mantis_pci *mantis) +{ + /* disable interrupt */ + mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); +} diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 61138639c36..e9f938d37c3 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -21,6 +21,21 @@ #ifndef __MANTIS_UART_H #define __MANTIS_UART_H +#define MANTIS_UART_CTL 0xe0 +#define MANTIS_UART_RXINT (1 << 4) +#define MANTIS_UART_RXFLUSH (1 << 2) + +#define MANTIS_UART_RXD 0xe8 +#define MANTIS_UART_BAUD 0xec + +#define MANTIS_UART_STAT 0xf0 +#define MANTIS_UART_RXFIFO_DATA (1 << 7) +#define MANTIS_UART_RXFIFO_EMPTY (1 << 6) +#define MANTIS_UART_RXFIFO_FULL (1 << 3) +#define MANTIS_UART_FRAME_ERR (1 << 2) +#define MANTIS_UART_PARITY_ERR (1 << 1) +#define MANTIS_UART_RXTHRESH_INT (1 << 0) + enum mantis_baud { MANTIS_BAUD_9600 = 0, MANTIS_BAUD_19200, @@ -30,9 +45,15 @@ enum mantis_baud { }; enum mantis_parity { - MANTIS_PARITY_NONE = 0, + MANTIS_PARITY_UNDEFINED = 0, MANTIS_PARITY_EVEN, - MANTIS_PARITY_ODD + MANTIS_PARITY_ODD, + MANTIS_PARITY_NONE }; +struct mantis_pci; + +extern int mantis_uart_init(struct mantis_pci *mantis); +extern void mantis_uart_exit(struct mantis_pci *mantis); + #endif // __MANTIS_UART_H diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 797c4e0c7ea..64cdfb8b709 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -88,6 +88,9 @@ struct mantis_hwconfig vp1033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index a2fe9d42d1e..28f3420b231 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -33,6 +33,9 @@ struct mantis_hwconfig vp1034_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 8eb1afdab11..90df80b80e1 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -31,6 +31,9 @@ struct mantis_hwconfig vp1041_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_188, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 4664d295921..1171e69b7e6 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -28,6 +28,9 @@ struct mantis_hwconfig vp2033_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; struct tda1002x_config philips_cu1216_config = { diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index f77be7b6491..ce73d6beb5c 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -28,6 +28,9 @@ struct mantis_hwconfig vp2040_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; struct tda10023_config tda10023_cu1216_config = { diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c new file mode 100644 index 00000000000..7f8918c2ce6 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3028.c @@ -0,0 +1,38 @@ +/* + Mantis VP-3028 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "mantis_common.h" +#include "mantis_vp3028.h" + +struct zl10353_config mantis_vp3028_config = { + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3028" +#define MANTIS_DEV_TYPE "DVB-T" + +struct mantis_hwconfig vp3028_mantis_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h new file mode 100644 index 00000000000..c51628ddf3c --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_vp3028.h @@ -0,0 +1,13 @@ +#ifndef __MANTIS_VP3028_H +#define __MANTIS_VP3028_H + +#include "dvb_frontend.h" +#include "mantis_common.h" +#include "zl10353.h" + +#define MANTIS_VP_3028_DVB_T 0x0028 + +extern struct zl10353_config mantis_vp3028_config; +extern struct mantis_hwconfig vp3028_mantis_config; + +#endif /* __MANTIS_VP3028_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index cab092ce230..9ca8040489d 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -32,6 +32,9 @@ struct mantis_hwconfig vp3030_mantis_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_188, + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, }; int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, -- cgit v1.2.3 From b3b961448f702339444036f94252ff2ba7a99feb Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:41:11 -0300 Subject: V4L/DVB (13795): [Mantis/Hopper] Code overhaul, add Hopper devices into the PCI ID list Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Kconfig | 22 +- drivers/media/dvb/mantis/Makefile | 42 ++-- drivers/media/dvb/mantis/hopper_cards.c | 260 ++++++++++++++++++++++ drivers/media/dvb/mantis/hopper_vp3028.c | 76 +++++++ drivers/media/dvb/mantis/hopper_vp3028.h | 10 + drivers/media/dvb/mantis/mantis_ca.c | 69 +++--- drivers/media/dvb/mantis/mantis_ca.h | 7 + drivers/media/dvb/mantis/mantis_cards.c | 279 +++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_common.h | 68 +++--- drivers/media/dvb/mantis/mantis_dma.c | 55 +++-- drivers/media/dvb/mantis/mantis_dma.h | 10 + drivers/media/dvb/mantis/mantis_dvb.c | 364 ++++++++++++++----------------- drivers/media/dvb/mantis/mantis_dvb.h | 15 ++ drivers/media/dvb/mantis/mantis_evm.c | 38 +++- drivers/media/dvb/mantis/mantis_hif.c | 60 +++-- drivers/media/dvb/mantis/mantis_hif.h | 2 +- drivers/media/dvb/mantis/mantis_i2c.c | 75 ++++--- drivers/media/dvb/mantis/mantis_i2c.h | 7 + drivers/media/dvb/mantis/mantis_ioc.c | 145 ++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 3 +- drivers/media/dvb/mantis/mantis_pci.c | 310 +++++++++----------------- drivers/media/dvb/mantis/mantis_pci.h | 7 + drivers/media/dvb/mantis/mantis_pcmcia.c | 22 +- drivers/media/dvb/mantis/mantis_reg.h | 40 +++- drivers/media/dvb/mantis/mantis_uart.c | 37 +++- drivers/media/dvb/mantis/mantis_uart.h | 2 +- drivers/media/dvb/mantis/mantis_vp1033.c | 98 ++++++--- drivers/media/dvb/mantis/mantis_vp1033.h | 13 +- drivers/media/dvb/mantis/mantis_vp1034.c | 66 ++++-- drivers/media/dvb/mantis/mantis_vp1034.h | 6 +- drivers/media/dvb/mantis/mantis_vp1041.c | 79 ++++++- drivers/media/dvb/mantis/mantis_vp1041.h | 14 +- drivers/media/dvb/mantis/mantis_vp2033.c | 95 ++++++-- drivers/media/dvb/mantis/mantis_vp2033.h | 11 +- drivers/media/dvb/mantis/mantis_vp2040.c | 141 +++++++++++- drivers/media/dvb/mantis/mantis_vp2040.h | 11 +- drivers/media/dvb/mantis/mantis_vp3030.c | 49 ++++- drivers/media/dvb/mantis/mantis_vp3030.h | 8 +- 38 files changed, 1881 insertions(+), 735 deletions(-) create mode 100644 drivers/media/dvb/mantis/hopper_cards.c create mode 100644 drivers/media/dvb/mantis/hopper_vp3028.c create mode 100644 drivers/media/dvb/mantis/hopper_vp3028.h create mode 100644 drivers/media/dvb/mantis/mantis_ca.h create mode 100644 drivers/media/dvb/mantis/mantis_cards.c create mode 100644 drivers/media/dvb/mantis/mantis_dma.h create mode 100644 drivers/media/dvb/mantis/mantis_dvb.h create mode 100644 drivers/media/dvb/mantis/mantis_i2c.h create mode 100644 drivers/media/dvb/mantis/mantis_ioc.c create mode 100644 drivers/media/dvb/mantis/mantis_pci.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index 4ba16d0ad96..aaf025097b4 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -1,6 +1,15 @@ +config MANTIS_CORE + tristate "Mantis/Hopper PCI bridge based devices" + depends on PCI && I2C + + help + Support for PCI cards based on the Mantis and Hopper PCi bridge. + + Say Y if you own such a device and want to use it. + config DVB_MANTIS tristate "MANTIS based cards" - depends on DVB_CORE && PCI && I2C + depends on MANTIS_CORE && DVB_CORE && PCI && I2C select DVB_MB86A16 select DVB_CU1216 select DVB_ZL10353 @@ -11,3 +20,14 @@ config DVB_MANTIS Say Y when you have a Mantis based DVB card and want to use it. If unsure say N. + +config DVB_HOPPER + tristate "HOPPER based cards" + depends on MANTIS_CORE && DVB_CORE && PCI && I2C + select DVB_ZL10353 + select DVB_PLL + help + Support for PCI cards based on the Hopper PCI bridge. + Say Y when you have a Hopper based DVB card and want to use it. + + If unsure say N diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index bb88cdc98ce..399c9018cdb 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -1,21 +1,27 @@ -mantis-objs = mantis_core.o \ - mantis_uart.o \ - mantis_dma.o \ - mantis_pci.o \ - mantis_i2c.o \ - mantis_dvb.o \ - mantis_evm.o \ - mantis_hif.o \ - mantis_ca.o \ - mantis_pcmcia.o \ - mantis_vp1033.o \ - mantis_vp1034.o \ - mantis_vp1041.o \ - mantis_vp2033.o \ - mantis_vp2040.o \ - mantis_vp3028.o \ - mantis_vp3030.o +mantis_core-objs := mantis_ioc.o \ + mantis_uart.o \ + mantis_dma.o \ + mantis_pci.o \ + mantis_i2c.o \ + mantis_dvb.o \ + mantis_evm.o \ + mantis_hif.o \ + mantis_ca.o \ + mantis_pcmcia.o -obj-$(CONFIG_DVB_MANTIS) += mantis.o +mantis-objs := mantis_cards.o \ + mantis_vp1033.o \ + mantis_vp1034.o \ + mantis_vp1041.o \ + mantis_vp2033.o \ + mantis_vp2040.o \ + mantis_vp3030.o + +hopper-objs := hopper_cards.o \ + hopper_vp3028.o + +obj-$(CONFIG_MANTIS_CORE) += mantis_core.o +obj-$(CONFIG_DVB_MANTIS) += mantis.o +obj-$(CONFIG_DVB_HOPPER) += hopper.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c new file mode 100644 index 00000000000..749e3f3dd06 --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" +#include "hopper_vp3028.h" +#include "mantis_dma.h" +#include "mantis_dvb.h" +#include "mantis_uart.h" +#include "mantis_ioc.h" +#include "mantis_pci.h" +#include "mantis_i2c.h" +#include "mantis_reg.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +#define DRIVER_NAME "Hopper" + +static char *label[10] = { + "DMA", + "IRQ-0", + "IRQ-1", + "OCERR", + "PABRT", + "RIPRR", + "PPERR", + "FTRGT", + "RISCI", + "RACK" +}; + +static int devs; + +static irqreturn_t hopper_irq_handler(int irq, void *dev_id) +{ + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + u32 rst_stat = 0, rst_mask = 0; + + struct mantis_pci *mantis; + struct mantis_ca *ca; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + ca = mantis->mantis_ca; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + if (!(stat & mask)) + return IRQ_NONE; + + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; + + rst_stat = mmread(MANTIS_GPIF_STATUS); + rst_stat &= rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); + mantis->gpif_status = rst_stat; + wake_up(&ca->hif_write_wq); + schedule_work(&ca->hif_evm_work); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); + schedule_work(&mantis->uart_work); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); + } + if (stat & MANTIS_INT_PPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); + } + if (stat & MANTIS_INT_FTRGT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(MANTIS_DEBUG, 0, " Stat=<%02x> Mask=<%02x>", stat, mask); + + dprintk(MANTIS_DEBUG, 0, "\n"); + return IRQ_HANDLED; +} + +static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + struct mantis_pci *mantis; + struct mantis_hwconfig *config; + int err = 0; + + mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); + err = -ENOMEM; + goto fail0; + } + + mantis->num = devs; + mantis->verbose = verbose; + mantis->pdev = pdev; + config = (struct mantis_hwconfig *) pci_id->driver_data; + config->irq_handler = &hopper_irq_handler; + mantis->hwconfig = config; + + err = mantis_pci_init(mantis); + if (err) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); + goto fail1; + } + + err = mantis_stream_control(mantis, STREAM_TO_HIF); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); + goto fail1; + } + + err = mantis_i2c_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); + goto fail2; + } + + err = mantis_get_mac(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); + goto fail2; + } + + err = mantis_dma_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); + goto fail3; + } + + err = mantis_dvb_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); + goto fail4; + } + devs++; + + return err; + +fail5: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); + mantis_dvb_exit(mantis); + +fail4: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); + mantis_dma_exit(mantis); + +fail3: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); + mantis_i2c_exit(mantis); + +fail2: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); + mantis_pci_exit(mantis); + +fail1: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); + kfree(mantis); + +fail0: + return err; +} + +static void __devexit hopper_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis) { +// mantis_uart_exit(mantis); + mantis_dvb_exit(mantis); + mantis_dma_exit(mantis); + mantis_i2c_exit(mantis); + mantis_pci_exit(mantis); + kfree(mantis); + } + return; + +} + +static struct pci_device_id hopper_pci_table[] = { + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config), + { } +}; + +static struct pci_driver hopper_pci_driver = { + .name = DRIVER_NAME, + .id_table = hopper_pci_table, + .probe = hopper_pci_probe, + .remove = hopper_pci_remove, +}; + +static int __devinit hopper_init(void) +{ + return pci_register_driver(&hopper_pci_driver); +} + +static void __devexit hopper_exit(void) +{ + return pci_unregister_driver(&hopper_pci_driver); +} + +module_init(hopper_init); +module_exit(hopper_exit); + +MODULE_DESCRIPTION("HOPPER driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c new file mode 100644 index 00000000000..ba0c7e58b7a --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -0,0 +1,76 @@ +/* + Mantis VP-3028 driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "zl10353.h" +#include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" +#include "hopper_vp3028.h" + +struct zl10353_config hopper_vp3028_config = { + .demod_address = 0x0f, +}; + +#define MANTIS_MODEL_NAME "VP-3028" +#define MANTIS_DEV_TYPE "DVB-T" + +static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + int err = 0; + + err = mantis_frontend_power(mantis, POWER_ON); + mantis_frontend_soft_reset(mantis); + + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&hopper_vp3028_config, adapter); + + if (!fe) + return -1; + + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp3028_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp3028_frontend_init, + .power = GPIF_A00, + .reset = GPIF_A03, +}; diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h new file mode 100644 index 00000000000..e8a3c2297bb --- /dev/null +++ b/drivers/media/dvb/mantis/hopper_vp3028.h @@ -0,0 +1,10 @@ +#ifndef __MANTIS_VP3028_H +#define __MANTIS_VP3028_H + +#include "mantis_common.h" + +#define MANTIS_VP_3028_DVB_T 0x0028 + +extern struct mantis_hwconfig vp3028_config; + +#endif /* __MANTIS_VP3028_H */ diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 7aa27e0703b..4151cba35e7 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -18,16 +18,30 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" #include "mantis_link.h" #include "mantis_hif.h" +#include "mantis_reg.h" + +#include "mantis_ca.h" static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) { struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); if (slot != 0) return -EINVAL; @@ -40,7 +54,7 @@ static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, in struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); if (slot != 0) return -EINVAL; @@ -53,7 +67,7 @@ static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 a struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); if (slot != 0) return -EINVAL; @@ -66,7 +80,7 @@ static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); if (slot != 0) return -EINVAL; @@ -79,7 +93,7 @@ static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); udelay(500); /* Wait.. */ mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */ udelay(500); @@ -95,7 +109,7 @@ static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); return 0; } @@ -105,8 +119,8 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); - mantis_set_direction(mantis, 1); /* Enable TS through CAM */ + dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); +// mantis_set_direction(mantis, 1); /* Enable TS through CAM */ return 0; } @@ -116,13 +130,13 @@ static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open struct mantis_ca *ca = en50221->data; struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); + dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); if (ca->slot_state == MODULE_INSERTED) { - dprintk(verbose, MANTIS_DEBUG, 1, "CA Module present and ready"); + dprintk(MANTIS_DEBUG, 1, "CA Module present and ready"); return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; } else { - dprintk(verbose, MANTIS_DEBUG, 1, "CA Module not present or not ready"); + dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready"); } return 0; @@ -130,20 +144,21 @@ static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open int mantis_ca_init(struct mantis_pci *mantis) { - struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; + struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; struct mantis_ca *ca; int ca_flags = 0, result; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis CA"); - if (!(ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL))) { - dprintk(verbose, MANTIS_ERROR, 1, "Out of memory!, exiting .."); + dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA"); + ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL); + if (!ca) { + dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting .."); result = -ENOMEM; goto err; } - ca->ca_priv = mantis; - mantis->mantis_ca = ca; - ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; + ca->ca_priv = mantis; + mantis->mantis_ca = ca; + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; /* register CA interface */ ca->en50221.owner = THIS_MODULE; ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; @@ -162,28 +177,32 @@ int mantis_ca_init(struct mantis_pci *mantis) init_waitqueue_head(&ca->hif_opdone_wq); init_waitqueue_head(&ca->hif_write_wq); - dprintk(verbose, MANTIS_ERROR, 1, "Registering EN50221 device"); - if ((result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1)) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "EN50221: Initialization failed"); + dprintk(MANTIS_ERROR, 1, "Registering EN50221 device"); + result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1); + if (result != 0) { + dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result); goto err; } - dprintk(verbose, MANTIS_ERROR, 1, "Registered EN50221 device"); + dprintk(MANTIS_ERROR, 1, "Registered EN50221 device"); mantis_evmgr_init(ca); return 0; err: kfree(ca); return result; } +EXPORT_SYMBOL_GPL(mantis_ca_init); void mantis_ca_exit(struct mantis_pci *mantis) { struct mantis_ca *ca = mantis->mantis_ca; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis CA exit"); + dprintk(MANTIS_DEBUG, 1, "Mantis CA exit"); mantis_evmgr_exit(ca); - dprintk(verbose, MANTIS_ERROR, 1, "Unregistering EN50221 device"); - dvb_ca_en50221_release(&ca->en50221); + dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device"); + if (ca) + dvb_ca_en50221_release(&ca->en50221); kfree(ca); } +EXPORT_SYMBOL_GPL(mantis_ca_exit); diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h new file mode 100644 index 00000000000..b7e48ee1fac --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ca.h @@ -0,0 +1,7 @@ +#ifndef __MANTIS_CA_H +#define __MANTIS_CA_H + +extern int mantis_ca_init(struct mantis_pci *mantis); +extern void mantis_ca_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_CA_H */ diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c new file mode 100644 index 00000000000..d486c7fcb45 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" + +#include "mantis_vp1033.h" +#include "mantis_vp1034.h" +#include "mantis_vp1041.h" +#include "mantis_vp2033.h" +#include "mantis_vp2040.h" +#include "mantis_vp3030.h" + +#include "mantis_dma.h" +#include "mantis_ca.h" +#include "mantis_dvb.h" +#include "mantis_uart.h" +#include "mantis_ioc.h" +#include "mantis_pci.h" +#include "mantis_i2c.h" +#include "mantis_reg.h" + +static unsigned int verbose; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); + +static int devs; + +#define DRIVER_NAME "Mantis" + +static char *label[10] = { + "DMA", + "IRQ-0", + "IRQ-1", + "OCERR", + "PABRT", + "RIPRR", + "PPERR", + "FTRGT", + "RISCI", + "RACK" +}; + + +static irqreturn_t mantis_irq_handler(int irq, void *dev_id) +{ + u32 stat = 0, mask = 0, lstat = 0, mstat = 0; + u32 rst_stat = 0, rst_mask = 0; + + struct mantis_pci *mantis; + struct mantis_ca *ca; + + mantis = (struct mantis_pci *) dev_id; + if (unlikely(mantis == NULL)) { + dprintk(MANTIS_ERROR, 1, "Mantis == NULL"); + return IRQ_NONE; + } + ca = mantis->mantis_ca; + + stat = mmread(MANTIS_INT_STAT); + mask = mmread(MANTIS_INT_MASK); + mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; + if (!(stat & mask)) + return IRQ_NONE; + + rst_mask = MANTIS_GPIF_WRACK | + MANTIS_GPIF_OTHERR | + MANTIS_SBUF_WSTO | + MANTIS_GPIF_EXTIRQ; + + rst_stat = mmread(MANTIS_GPIF_STATUS); + rst_stat &= rst_mask; + mmwrite(rst_stat, MANTIS_GPIF_STATUS); + + mantis->mantis_int_stat = stat; + mantis->mantis_int_mask = mask; + dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask); + if (stat & MANTIS_INT_RISCEN) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]); + } + if (stat & MANTIS_INT_IRQ0) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]); + mantis->gpif_status = rst_stat; + wake_up(&ca->hif_write_wq); + schedule_work(&ca->hif_evm_work); + } + if (stat & MANTIS_INT_IRQ1) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]); + schedule_work(&mantis->uart_work); + } + if (stat & MANTIS_INT_OCERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]); + } + if (stat & MANTIS_INT_PABORT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]); + } + if (stat & MANTIS_INT_RIPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]); + } + if (stat & MANTIS_INT_PPERR) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]); + } + if (stat & MANTIS_INT_FTRGT) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]); + } + if (stat & MANTIS_INT_RISCI) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]); + mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; + tasklet_schedule(&mantis->tasklet); + } + if (stat & MANTIS_INT_I2CDONE) { + dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]); + wake_up(&mantis->i2c_wq); + } + mmwrite(stat, MANTIS_INT_STAT); + stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | + MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | + MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | + MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | + MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | + MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | + MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | + MANTIS_INT_PABORT | MANTIS_INT_RIPERR | + MANTIS_INT_PPERR | MANTIS_INT_FTRGT | + MANTIS_INT_RISCI); + + if (stat) + dprintk(MANTIS_DEBUG, 0, " Stat=<%02x> Mask=<%02x>", stat, mask); + + dprintk(MANTIS_DEBUG, 0, "\n"); + return IRQ_HANDLED; +} + +static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + struct mantis_pci *mantis; + struct mantis_hwconfig *config; + int err = 0; + + mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + if (mantis == NULL) { + printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); + err = -ENOMEM; + goto fail0; + } + + mantis->num = devs; + mantis->verbose = verbose; + mantis->pdev = pdev; + config = (struct mantis_hwconfig *) pci_id->driver_data; + config->irq_handler = &mantis_irq_handler; + mantis->hwconfig = config; + + err = mantis_pci_init(mantis); + if (err) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err); + goto fail1; + } + + err = mantis_stream_control(mantis, STREAM_TO_HIF); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err); + goto fail1; + } + + err = mantis_i2c_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err); + goto fail2; + } + + err = mantis_get_mac(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err); + goto fail2; + } + + err = mantis_dma_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err); + goto fail3; + } + + err = mantis_dvb_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); + goto fail4; + } + devs++; + + return err; + +fail5: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); + mantis_dvb_exit(mantis); + +fail4: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); + mantis_dma_exit(mantis); + +fail3: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err); + mantis_i2c_exit(mantis); + +fail2: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err); + mantis_pci_exit(mantis); + +fail1: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err); + kfree(mantis); + +fail0: + return err; +} + +static void __devexit mantis_pci_remove(struct pci_dev *pdev) +{ + struct mantis_pci *mantis = pci_get_drvdata(pdev); + + if (mantis) { + mantis_uart_exit(mantis); +// mantis_ca_exit(mantis); + mantis_dvb_exit(mantis); + mantis_dma_exit(mantis); + mantis_i2c_exit(mantis); + mantis_pci_exit(mantis); + kfree(mantis); + } + return; +} + +static struct pci_device_id mantis_pci_table[] = { + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config), + MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config), + MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config), + MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config), + MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config), + MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config), + MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config), + { } +}; + +static struct pci_driver mantis_pci_driver = { + .name = DRIVER_NAME, + .id_table = mantis_pci_table, + .probe = mantis_pci_probe, + .remove = mantis_pci_remove, +}; + +static int __devinit mantis_init(void) +{ + return pci_register_driver(&mantis_pci_driver); +} + +static void __devexit mantis_exit(void) +{ + return pci_unregister_driver(&mantis_pci_driver); +} + +module_init(mantis_init); +module_exit(mantis_exit); + +MODULE_DESCRIPTION("MANTIS driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 6a02adf1ab4..e912c5962e3 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -21,20 +21,9 @@ #ifndef __MANTIS_COMMON_H #define __MANTIS_COMMON_H -#include -#include -#include -#include #include #include -#include "dvbdev.h" -#include "dvb_demux.h" -#include "dmxdev.h" -#include "dvb_frontend.h" -#include "dvb_net.h" -#include -#include "mantis_reg.h" #include "mantis_uart.h" #include "mantis_link.h" @@ -44,18 +33,18 @@ #define MANTIS_INFO 2 #define MANTIS_DEBUG 3 -#define dprintk(x, y, z, format, arg...) do { \ +#define dprintk(y, z, format, arg...) do { \ if (z) { \ - if ((x > MANTIS_ERROR) && (x > y)) \ + if ((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y)) \ printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ - else if ((x > MANTIS_NOTICE) && (x > y)) \ + else if ((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y)) \ printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ - else if ((x > MANTIS_INFO) && (x > y)) \ + else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y)) \ printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ - else if ((x > MANTIS_DEBUG) && (x > y)) \ + else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y)) \ printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ } else { \ - if (x > y) \ + if (mantis->verbose > y) \ printk(format , ##arg); \ } \ } while(0) @@ -63,8 +52,8 @@ #define mwrite(dat, addr) writel((dat), addr) #define mread(addr) readl(addr) -#define mmwrite(dat, addr) mwrite((dat), (mantis->mantis_mmio + (addr))) -#define mmread(addr) mread(mantis->mantis_mmio + (addr)) +#define mmwrite(dat, addr) mwrite((dat), (mantis->mmio + (addr))) +#define mmread(addr) mread(mantis->mmio + (addr)) #define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) #define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) #define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) @@ -72,6 +61,22 @@ #define MANTIS_TS_188 0 #define MANTIS_TS_204 1 +#define TWINHAN_TECHNOLOGIES 0x1822 +#define MANTIS 0x4e35 + +#define TECHNISAT 0x1ae4 +#define TERRATEC 0x153b + +#define MAKE_ENTRY(__subven, __subdev, __configptr) { \ + .vendor = TWINHAN_TECHNOLOGIES, \ + .device = MANTIS, \ + .subvendor = (__subven), \ + .subdevice = (__subdev), \ + .driver_data = (unsigned long) (__configptr) \ +} + +struct mantis_pci; + struct mantis_hwconfig { char *model_name; char *dev_type; @@ -80,6 +85,12 @@ struct mantis_hwconfig { enum mantis_baud baud_rate; enum mantis_parity parity; u32 bytes; + + irqreturn_t (*irq_handler)(int irq, void *dev_id); + int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe); + + u8 power; + u8 reset; }; struct mantis_pci { @@ -96,7 +107,7 @@ struct mantis_pci { struct pci_dev *pdev; unsigned long mantis_addr; - volatile void __iomem *mantis_mmio; + void __iomem *mmio; u8 irq; u8 revision; @@ -156,19 +167,4 @@ struct mantis_pci { #define MANTIS_HIF_STATUS (mantis->gpio_status) -extern unsigned int verbose; -extern unsigned int devs; -extern unsigned int i2c; -extern int mantis_dvb_init(struct mantis_pci *mantis); -extern int mantis_frontend_init(struct mantis_pci *mantis); -extern int mantis_dvb_exit(struct mantis_pci *mantis); -extern void mantis_dma_xfer(unsigned long data); -extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); - -extern void mantis_set_direction(struct mantis_pci *mantis, int direction); - -extern int mantis_ca_init(struct mantis_pci *mantis); -extern void mantis_ca_exit(struct mantis_pci *mantis); - - -#endif //__MANTIS_COMMON_H +#endif /* __MANTIS_COMMON_H */ diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index d15a1eb980c..8ebcd96b2b7 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -18,9 +18,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_dma.h" #define RISC_WRITE (0x01 << 28) #define RISC_JUMP (0x07 << 28) @@ -38,7 +54,7 @@ int mantis_dma_exit(struct mantis_pci *mantis) { if (mantis->buf_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "DMA=0x%lx cpu=0x%p size=%d", (unsigned long) mantis->buf_dma, mantis->buf_cpu, @@ -50,7 +66,7 @@ int mantis_dma_exit(struct mantis_pci *mantis) mantis->buf_cpu = NULL; } if (mantis->risc_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "RISC=0x%lx cpu=0x%p size=%lx", (unsigned long) mantis->risc_dma, mantis->risc_cpu, @@ -64,6 +80,7 @@ int mantis_dma_exit(struct mantis_pci *mantis) return 0; } +EXPORT_SYMBOL_GPL(mantis_dma_exit); static inline int mantis_alloc_buffers(struct mantis_pci *mantis) { @@ -72,12 +89,12 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis) MANTIS_BUF_SIZE, &mantis->buf_dma); if (!mantis->buf_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "DMA buffer allocation failed"); goto err; } - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "DMA=0x%lx cpu=0x%p size=%d", (unsigned long) mantis->buf_dma, mantis->buf_cpu, MANTIS_BUF_SIZE); @@ -88,14 +105,14 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis) &mantis->risc_dma); if (!mantis->risc_cpu) { - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "RISC program allocation failed"); mantis_dma_exit(mantis); goto err; } - dprintk(verbose, MANTIS_ERROR, 1, + dprintk(MANTIS_ERROR, 1, "RISC=0x%lx cpu=0x%p size=%lx", (unsigned long) mantis->risc_dma, mantis->risc_cpu, MANTIS_RISC_SIZE); @@ -103,7 +120,7 @@ static inline int mantis_alloc_buffers(struct mantis_pci *mantis) return 0; err: - dprintk(verbose, MANTIS_ERROR, 1, "Out of memory (?) ....."); + dprintk(MANTIS_ERROR, 1, "Out of memory (?) ....."); return -ENOMEM; } @@ -117,12 +134,11 @@ static inline int mantis_calc_lines(struct mantis_pci *mantis) mantis->line_count <<= 1; } - dprintk(verbose, MANTIS_DEBUG, 1, - "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", + dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]", MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count); if (mantis->line_count > 255) { - dprintk(verbose, MANTIS_ERROR, 1, "Buffer size error"); + dprintk(MANTIS_ERROR, 1, "Buffer size error"); return -EINVAL; } @@ -133,9 +149,9 @@ int mantis_dma_init(struct mantis_pci *mantis) { int err = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DMA init"); + dprintk(MANTIS_DEBUG, 1, "Mantis DMA init"); if (mantis_alloc_buffers(mantis) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Error allocating DMA buffer"); + dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); // Stop RISC Engine // mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); @@ -144,7 +160,7 @@ int mantis_dma_init(struct mantis_pci *mantis) goto err; } if ((err = mantis_calc_lines(mantis)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis calc lines failed"); + dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); goto err; } @@ -153,20 +169,21 @@ int mantis_dma_init(struct mantis_pci *mantis) err: return err; } +EXPORT_SYMBOL_GPL(mantis_dma_init); static inline void mantis_risc_program(struct mantis_pci *mantis) { u32 buf_pos = 0; u32 line; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis create RISC program"); + dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program"); RISC_FLUSH(); - dprintk(verbose, MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", + dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u", mantis->line_count, mantis->line_bytes); for (line = 0; line < mantis->line_count; line++) { - dprintk(verbose, MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); + dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line); if (!(buf_pos % MANTIS_BLOCK_BYTES)) { RISC_INSTR(RISC_WRITE | RISC_IRQ | @@ -186,7 +203,7 @@ static inline void mantis_risc_program(struct mantis_pci *mantis) void mantis_dma_start(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Start DMA engine"); + dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine"); mantis_risc_program(mantis); mmwrite(mantis->risc_dma, MANTIS_RISC_START); @@ -208,7 +225,7 @@ void mantis_dma_stop(struct mantis_pci *mantis) stat = mmread(MANTIS_INT_STAT); mask = mmread(MANTIS_INT_MASK); - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); + dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); @@ -229,7 +246,7 @@ void mantis_dma_xfer(unsigned long data) struct mantis_hwconfig *config = mantis->hwconfig; while (mantis->last_block != mantis->finished_block) { - dprintk(verbose, MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", + dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", mantis->last_block, mantis->finished_block); (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h new file mode 100644 index 00000000000..4cba8763536 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dma.h @@ -0,0 +1,10 @@ +#ifndef __MANTIS_DMA_H +#define __MANTIS_DMA_H + +extern int mantis_dma_init(struct mantis_pci *mantis); +extern int mantis_dma_exit(struct mantis_pci *mantis); +extern void mantis_dma_start(struct mantis_pci *mantis); +extern void mantis_dma_stop(struct mantis_pci *mantis); +extern void mantis_dma_xfer(unsigned long data); + +#endif /* __MANTIS_DMA_H */ diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index de18bb97d8e..be911d76daa 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -17,65 +17,86 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include -#include "mantis_common.h" -#include "mantis_core.h" + +#include +#include +#include +#include +#include +#include #include "dmxdev.h" #include "dvbdev.h" #include "dvb_demux.h" #include "dvb_frontend.h" -#include "mantis_vp1033.h" -#include "mantis_vp1034.h" -#include "mantis_vp1041.h" -#include "mantis_vp2033.h" -#include "mantis_vp2040.h" -#include "mantis_vp3030.h" +#include "dvb_net.h" -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +#include "mantis_common.h" +#include "mantis_dma.h" +#include "mantis_ca.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" -/* Tuner power supply control */ -void mantis_fe_powerup(struct mantis_pci *mantis) -{ - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power ON"); - gpio_set_bits(mantis, 0x0c, 1); - msleep_interruptible(100); - gpio_set_bits(mantis, 0x0c, 1); - msleep_interruptible(100); -} +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -void mantis_fe_powerdown(struct mantis_pci *mantis) +int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power) { - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Power OFF"); - gpio_set_bits(mantis, 0x0c, 0); -} + struct mantis_hwconfig *config = mantis->hwconfig; + + switch (power) { + case POWER_ON: + dprintk(MANTIS_DEBUG, 1, "Power ON"); + gpio_set_bits(mantis, config->power, POWER_ON); + msleep(100); + gpio_set_bits(mantis, config->power, POWER_ON); + msleep(100); + break; -static int mantis_fe_reset(struct dvb_frontend *fe) -{ - struct mantis_pci *mantis = fe->dvb->priv; + case POWER_OFF: + dprintk(MANTIS_DEBUG, 1, "Power OFF"); + gpio_set_bits(mantis, config->power, POWER_OFF); + msleep(100); + break; - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); + default: + dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power); + return -1; + } return 0; } +EXPORT_SYMBOL_GPL(mantis_frontend_power); -static int mantis_frontend_reset(struct mantis_pci *mantis) +void mantis_frontend_soft_reset(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Frontend Reset"); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 0); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); - msleep_interruptible(100); - gpio_set_bits(mantis, 13, 1); + struct mantis_hwconfig *config = mantis->hwconfig; + + dprintk(MANTIS_DEBUG, 1, "Frontend RESET"); + gpio_set_bits(mantis, config->reset, 0); + msleep(100); + gpio_set_bits(mantis, config->reset, 0); + msleep(100); + gpio_set_bits(mantis, config->reset, 1); + msleep(100); + gpio_set_bits(mantis, config->reset, 1); + msleep(100); + + return; +} +EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset); + +static int mantis_frontend_shutdown(struct mantis_pci *mantis) +{ + int err; + + mantis_frontend_soft_reset(mantis); + err = mantis_frontend_power(mantis, POWER_OFF); + if (err != 0) { + dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err); + return 1; + } return 0; } @@ -85,18 +106,17 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct mantis_pci *mantis = dvbdmx->priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Start feed"); + dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed"); if (!dvbdmx->dmx.frontend) { - dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + dprintk(MANTIS_DEBUG, 1, "no frontend ?"); return -EINVAL; } + mantis->feeds++; - dprintk(verbose, MANTIS_DEBUG, 1, - "mantis start feed, feeds=%d", - mantis->feeds); + dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d", mantis->feeds); if (mantis->feeds == 1) { - dprintk(verbose, MANTIS_DEBUG, 1, "mantis start feed & dma"); + dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); printk("mantis start feed & dma\n"); mantis_dma_start(mantis); } @@ -109,95 +129,129 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) struct dvb_demux *dvbdmx = dvbdmxfeed->demux; struct mantis_pci *mantis = dvbdmx->priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); + dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed"); if (!dvbdmx->dmx.frontend) { - dprintk(verbose, MANTIS_DEBUG, 1, "no frontend ?"); + dprintk(MANTIS_DEBUG, 1, "no frontend ?"); return -EINVAL; } + mantis->feeds--; if (mantis->feeds == 0) { - dprintk(verbose, MANTIS_DEBUG, 1, "mantis stop feed and dma"); + dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); printk("mantis stop feed and dma\n"); mantis_dma_stop(mantis); } + return 0; } int __devinit mantis_dvb_init(struct mantis_pci *mantis) { - int result; + struct mantis_hwconfig *config = mantis->hwconfig; + int result = -1; + + dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter"); + + result = dvb_register_adapter(&mantis->dvb_adapter, + "Mantis DVB adapter", + THIS_MODULE, + &mantis->pdev->dev, + adapter_nr); - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_register_adapter"); - if (dvb_register_adapter(&mantis->dvb_adapter, - "Mantis dvb adapter", THIS_MODULE, - &mantis->pdev->dev, - adapter_nr) < 0) { + if (result < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Error registering adapter"); + dprintk(MANTIS_ERROR, 1, "Error registering adapter"); return -ENODEV; } - mantis->dvb_adapter.priv = mantis; - mantis->demux.dmx.capabilities = DMX_TS_FILTERING | + + mantis->dvb_adapter.priv = mantis; + mantis->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING; - mantis->demux.priv = mantis; - mantis->demux.filternum = 256; - mantis->demux.feednum = 256; - mantis->demux.start_feed = mantis_dvb_start_feed; - mantis->demux.stop_feed = mantis_dvb_stop_feed; - mantis->demux.write_to_decoder = NULL; - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmx_init"); - if ((result = dvb_dmx_init(&mantis->demux)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + mantis->demux.priv = mantis; + mantis->demux.filternum = 256; + mantis->demux.feednum = 256; + mantis->demux.start_feed = mantis_dvb_start_feed; + mantis->demux.stop_feed = mantis_dvb_stop_feed; + mantis->demux.write_to_decoder = NULL; + + dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init"); + result = dvb_dmx_init(&mantis->demux); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err0; } - mantis->dmxdev.filternum = 256; - mantis->dmxdev.demux = &mantis->demux.dmx; - mantis->dmxdev.capabilities = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_dmxdev_init"); - if ((result = dvb_dmxdev_init(&mantis->dmxdev, - &mantis->dvb_adapter)) < 0) { - - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmxdev_init failed, ERROR=%d", result); + + mantis->dmxdev.filternum = 256; + mantis->dmxdev.demux = &mantis->demux.dmx; + mantis->dmxdev.capabilities = 0; + dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init"); + + result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter); + if (result < 0) { + + dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); goto err1; } - mantis->fe_hw.source = DMX_FRONTEND_0; - if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, - &mantis->fe_hw)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + mantis->fe_hw.source = DMX_FRONTEND_0; + result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err2; } - mantis->fe_mem.source = DMX_MEMORY_FE; - if ((result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, - &mantis->fe_mem)) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + mantis->fe_mem.source = DMX_MEMORY_FE; + result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx,&mantis->fe_mem); + if (result < 0) { + dprintk(MANTIS_ERROR, 1,"dvb_dmx_init failed, ERROR=%d", result); goto err3; } - if ((result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, - &mantis->fe_hw)) < 0) { - - dprintk(verbose, MANTIS_ERROR, 1, - "dvb_dmx_init failed, ERROR=%d", result); + result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err4; } + dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx); tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis); - mantis_frontend_init(mantis); - mantis_ca_init(mantis); + if (mantis->hwconfig) { + result = config->frontend_init(mantis, mantis->fe); + if (result < 0) { + dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); + goto err5; + } else { +// if (mantis->dvb_adapter == NULL) { +// dprintk(MANTIS_ERROR, 1, "DVB adapter "); +// goto err5; +// } + if (mantis->fe == NULL) { + dprintk(MANTIS_ERROR, 1, "FE "); + goto err5; + } + + if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { + dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed"); + + if (mantis->fe->ops.release) + mantis->fe->ops.release(mantis->fe); + + mantis->fe = NULL; + goto err5; + } + } + } return 0; - /* Error conditions .. */ + /* Error conditions .. */ +err5: + tasklet_kill(&mantis->tasklet); + dvb_net_release(&mantis->dvbnet); err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); err3: @@ -211,115 +265,17 @@ err0: return result; } +EXPORT_SYMBOL_GPL(mantis_dvb_init); -int __devinit mantis_frontend_init(struct mantis_pci *mantis) +int __devexit mantis_dvb_exit(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis frontend Init"); - mantis_fe_powerup(mantis); - mantis_frontend_reset(mantis); - dprintk(verbose, MANTIS_DEBUG, 1, "Device ID=%02x", mantis->subsystem_device); - switch (mantis->subsystem_device) { - case MANTIS_VP_1033_DVB_S: // VP-1033 - dprintk(verbose, MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); - mantis->fe = stv0299_attach(&lgtdqcs001f_config, - &mantis->adapter); - - if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "found STV0299 DVB-S frontend @ 0x%02x", - lgtdqcs001f_config.demod_address); - - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-S STV0299 frontend attach success"); - } - break; - case MANTIS_VP_1034_DVB_S: // VP-1034 - dprintk(verbose, MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); - mantis->fe = mb86a16_attach(&vp1034_config, &mantis->adapter); - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found MB86A16 DVB-S/DSS frontend @0x%02x", - vp1034_config.demod_address); + int err; - } - break; - case MANTIS_VP_1041_DVB_S2: - case TECHNISAT_SKYSTAR_HD2: - mantis->fe = stb0899_attach(&vp1041_config, &mantis->adapter); - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", - vp1041_config.demod_address); - - if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, &mantis->adapter)) { - if (!lnbp21_attach(mantis->fe, &mantis->adapter, 0, 0)) { - printk("%s: No LNBP21 found!\n", __FUNCTION__); - mantis->fe = NULL; - } - } else { - mantis->fe = NULL; - } - } - break; - case MANTIS_VP_2033_DVB_C: // VP-2033 - case MANTIS_VP_2040_DVB_C: // VP-2040 - case TERRATEC_CINERGY_C_PCI: - case TECHNISAT_CABLESTAR_HD2: - dprintk(verbose, MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - mantis->fe = tda10021_attach(&philips_cu1216_config, - &mantis->adapter, - read_pwm(mantis)); - - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", - philips_cu1216_config.demod_address); - } else { - mantis->fe = tda10023_attach(&tda10023_cu1216_config, - &mantis->adapter, - read_pwm(mantis)); - - if (mantis->fe) { - dprintk(verbose, MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", - philips_cu1216_config.demod_address); - } - } - if (mantis->fe) { - mantis->fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set; - dprintk(verbose, MANTIS_ERROR, 1, - "Mantis DVB-C Philips CU1216 frontend attach success"); - } - break; - default: - dprintk(verbose, MANTIS_DEBUG, 1, "Unknown frontend:[0x%02x]", - mantis->sub_device_id); + err = mantis_frontend_shutdown(mantis); + if (err != 0) + dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); - return -ENODEV; - } - if (mantis->fe == NULL) { - dprintk(verbose, MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); - return -ENODEV; - } else { - if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) { - dprintk(verbose, MANTIS_ERROR, 1, - "ERROR: Frontend registration failed"); - - if (mantis->fe->ops.release) - mantis->fe->ops.release(mantis->fe); - - mantis->fe = NULL; - return -ENODEV; - } - } - - return 0; -} - -int __devexit mantis_dvb_exit(struct mantis_pci *mantis) -{ - mantis_ca_exit(mantis); +// mantis_ca_exit(mantis); tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); @@ -329,8 +285,10 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) if (mantis->fe) dvb_unregister_frontend(mantis->fe); - dprintk(verbose, MANTIS_DEBUG, 1, "dvb_unregister_adapter"); + + dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); dvb_unregister_adapter(&mantis->dvb_adapter); return 0; } +EXPORT_SYMBOL_GPL(mantis_dvb_exit); diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h new file mode 100644 index 00000000000..31ebbb47df3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_dvb.h @@ -0,0 +1,15 @@ +#ifndef __MANTIS_DVB_H +#define __MANTIS_DVB_H + +enum mantis_power { + POWER_OFF = 0, + POWER_ON = 1 +}; + +extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power); +extern void mantis_frontend_soft_reset(struct mantis_pci *mantis); + +extern int mantis_dvb_init(struct mantis_pci *mantis); +extern int mantis_dvb_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_DVB_H */ diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9be55f7942d..2005b2489b7 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -18,9 +18,23 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" #include "mantis_link.h" #include "mantis_hif.h" +#include "mantis_reg.h" static void mantis_hifevm_work(struct work_struct *work) { @@ -34,7 +48,7 @@ static void mantis_hifevm_work(struct work_struct *work) if (gpif_stat & MANTIS_GPIF_DETSTAT) { if (gpif_stat & MANTIS_CARD_PLUGIN) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_plugin(ca); dvb_ca_en50221_camchange_irq(&ca->en50221, @@ -43,7 +57,7 @@ static void mantis_hifevm_work(struct work_struct *work) } } else { if (gpif_stat & MANTIS_CARD_PLUGOUT) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num); mmwrite(0xdada0000, MANTIS_CARD_RESET); mantis_event_cam_unplug(ca); dvb_ca_en50221_camchange_irq(&ca->en50221, @@ -53,28 +67,28 @@ static void mantis_hifevm_work(struct work_struct *work) } if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num); if (mantis->gpif_status & MANTIS_SBUF_WSTO) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num); if (mantis->gpif_status & MANTIS_GPIF_OTHERR) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num); if (gpif_stat & MANTIS_SBUF_OVFLW) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num); if (gpif_stat & MANTIS_GPIF_BRRDY) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num); if (gpif_stat & MANTIS_GPIF_INTSTAT) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num); if (gpif_stat & MANTIS_SBUF_EMPTY) - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num); if (gpif_stat & MANTIS_SBUF_OPDONE) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num); ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL; ca->hif_event = MANTIS_SBUF_OPDONE; wake_up(&ca->hif_opdone_wq); @@ -85,7 +99,7 @@ int mantis_evmgr_init(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); + dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager"); INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work); mantis_pcmcia_init(ca); schedule_work(&ca->hif_evm_work); @@ -97,7 +111,7 @@ void mantis_evmgr_exit(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; - dprintk(verbose, MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); + dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting"); flush_scheduled_work(); mantis_hif_exit(ca); mantis_pcmcia_exit(ca); diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 99a9724cbaf..bb05427fdeb 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -18,10 +18,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" + #include "mantis_hif.h" #include "mantis_link.h" /* temporary due to physical layer stuff */ +#include "mantis_reg.h" + static int mantis_hif_data_available(struct mantis_ca *ca) { struct mantis_pci *mantis = ca->ca_priv; @@ -31,7 +49,7 @@ static int mantis_hif_data_available(struct mantis_ca *ca) ca->sbuf_status & MANTIS_SBUF_DATA_AVAIL, msecs_to_jiffies(500)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); rc = -EREMOTEIO; } ca->sbuf_status &= ~MANTIS_SBUF_DATA_AVAIL; @@ -48,10 +66,10 @@ static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) ca->hif_event & MANTIS_SBUF_OPDONE, msecs_to_jiffies(500)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num); rc = -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); + dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete"); ca->hif_event &= ~MANTIS_SBUF_OPDONE; return rc; } @@ -66,22 +84,22 @@ static int mantis_hif_write_wait(struct mantis_ca *ca) mantis->gpif_status & MANTIS_GPIF_WRACK, msecs_to_jiffies(500)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num); rc = -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "Write Acknowledged"); + dprintk(MANTIS_DEBUG, 1, "Write Acknowledged"); mantis->gpif_status &= ~MANTIS_GPIF_WRACK; while (!opdone) { opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE); udelay(500); timeout++; if (timeout > 100) { - dprintk(verbose, MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num); rc = -ETIMEDOUT; break; } } - dprintk(verbose, MANTIS_DEBUG, 1, "HIF Write success"); + dprintk(MANTIS_DEBUG, 1, "HIF Write success"); return rc; } @@ -91,7 +109,7 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0, data, count = 4; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_PCMCIAIOM; @@ -104,13 +122,13 @@ int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr) mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); mutex_unlock(&ca->ca_lock); - dprintk(verbose, MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); + dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data); return (data >> 24) & 0xff; } @@ -120,7 +138,7 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_HIFRDWRN; hif_addr &= ~MANTIS_GPIF_PCMCIAREG; @@ -133,11 +151,11 @@ int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); + dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr); mutex_unlock(&ca->ca_lock); return 0; @@ -148,7 +166,7 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) struct mantis_pci *mantis = ca->ca_priv; u32 data, hif_addr = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr |= MANTIS_GPIF_PCMCIAIOM; @@ -161,12 +179,12 @@ int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr) mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); if (mantis_hif_sbuf_opdone_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } data = mmread(MANTIS_GPIF_DIN); - dprintk(verbose, MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); + dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data); udelay(50); mutex_unlock(&ca->ca_lock); @@ -178,7 +196,7 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) struct mantis_pci *mantis = ca->ca_priv; u32 hif_addr = 0; - dprintk(verbose, MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num); mutex_lock(&ca->ca_lock); hif_addr &= ~MANTIS_GPIF_PCMCIAREG; hif_addr &= ~MANTIS_GPIF_HIFRDWRN; @@ -190,11 +208,11 @@ int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data) mmwrite(data, MANTIS_GPIF_DOUT); if (mantis_hif_write_wait(ca) != 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num); mutex_unlock(&ca->ca_lock); return -EREMOTEIO; } - dprintk(verbose, MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); + dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr); mutex_unlock(&ca->ca_lock); udelay(50); @@ -208,7 +226,7 @@ int mantis_hif_init(struct mantis_ca *ca) u32 irqcfg; slot[0].slave_cfg = 0x70773028; - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num); mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -230,7 +248,7 @@ void mantis_hif_exit(struct mantis_ca *ca) struct mantis_pci *mantis = ca->ca_priv; u32 irqcfg; - dprintk(verbose, MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); + dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num); mutex_lock(&ca->ca_lock); irqcfg = mmread(MANTIS_GPIF_IRQCFG); irqcfg &= ~MANTIS_MASK_BRRDY; diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h index 7ef45cec19d..f960c0aeacc 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -26,4 +26,4 @@ #define MANTIS_HIF_IOMRD 3 #define MANTIS_HIF_IOMWR 4 -#endif // __MANTIS_HIF_H +#endif /* __MANTIS_HIF_H */ diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 45d9e6bd962..ba55f0a9a10 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -18,15 +18,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include #include #include -#include -#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_i2c.h" #define I2C_HW_B_MANTIS 0x1c @@ -35,20 +40,21 @@ static int mantis_ack_wait(struct mantis_pci *mantis) int rc = 0; u32 timeout = 0; - if (wait_event_interruptible_timeout(mantis->i2c_wq, - mantis->mantis_int_stat & MANTIS_INT_I2CDONE, - msecs_to_jiffies(50)) == -ERESTARTSYS) { + if (wait_event_timeout(mantis->i2c_wq, + mantis->mantis_int_stat & MANTIS_INT_I2CDONE, + msecs_to_jiffies(50)) == -ERESTARTSYS) { - dprintk(verbose, MANTIS_DEBUG, 1, "Master !I2CDONE"); + dprintk(MANTIS_DEBUG, 1, "Master !I2CDONE"); rc = -EREMOTEIO; } + while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { - dprintk(verbose, MANTIS_DEBUG, 1, "Waiting for Slave RACK"); + dprintk(MANTIS_DEBUG, 1, "Waiting for Slave RACK"); mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); msleep(5); timeout++; if (timeout > 500) { - dprintk(verbose, MANTIS_ERROR, 1, "Slave RACK Fail !"); + dprintk(MANTIS_ERROR, 1, "Slave RACK Fail !"); rc = -EREMOTEIO; break; } @@ -62,7 +68,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { @@ -77,14 +83,14 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(rxd, MANTIS_I2CDATA_CTL); if (mantis_ack_wait(mantis) != 0) { - dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + dprintk(MANTIS_DEBUG, 1, "ACK failed"); return -EREMOTEIO; } rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); - dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); + dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); } - dprintk(verbose, MANTIS_INFO, 0, "]\n"); + dprintk(MANTIS_INFO, 0, "]\n"); return 0; } @@ -94,11 +100,11 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg int i; u32 txd = 0; - dprintk(verbose, MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", + dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); for (i = 0; i < msg->len; i++) { - dprintk(verbose, MANTIS_INFO, 0, "%02x ", msg->buf[i]); + dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); txd = (msg->addr << 25) | (msg->buf[i] << 8) | MANTIS_I2C_RATE_3 | MANTIS_I2C_STOP @@ -110,11 +116,11 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(txd, MANTIS_I2CDATA_CTL); if (mantis_ack_wait(mantis) != 0) { - dprintk(verbose, MANTIS_DEBUG, 1, "ACK failed"); + dprintk(MANTIS_DEBUG, 1, "ACK failed"); return -EREMOTEIO; } } - dprintk(verbose, MANTIS_INFO, 0, "]\n"); + dprintk(MANTIS_INFO, 0, "]\n"); return 0; } @@ -154,43 +160,46 @@ static struct i2c_algorithm mantis_algo = { .functionality = mantis_i2c_func, }; -static struct i2c_adapter mantis_i2c_adapter = { - .owner = THIS_MODULE, - .name = "Mantis I2C", - .id = I2C_HW_B_MANTIS, - .class = I2C_CLASS_TV_DIGITAL, - .algo = &mantis_algo, -}; - int __devinit mantis_i2c_init(struct mantis_pci *mantis) { u32 intstat, intmask; struct i2c_adapter *i2c_adapter = &mantis->adapter; struct pci_dev *pdev = mantis->pdev; + init_waitqueue_head(&mantis->i2c_wq); mutex_init(&mantis->i2c_lock); - memcpy(i2c_adapter, &mantis_i2c_adapter, sizeof (mantis_i2c_adapter)); + strncpy(i2c_adapter->name, "Mantis I2C", sizeof (i2c_adapter->name)); i2c_set_adapdata(i2c_adapter, mantis); - i2c_adapter->dev.parent = &pdev->dev; + i2c_adapter->owner = THIS_MODULE; + i2c_adapter->class = I2C_CLASS_TV_DIGITAL; + i2c_adapter->algo = &mantis_algo; + i2c_adapter->algo_data = NULL; + i2c_adapter->id = I2C_HW_B_MANTIS; + i2c_adapter->timeout = 500; + i2c_adapter->retries = 3; + i2c_adapter->dev.parent = &pdev->dev; + mantis->i2c_rc = i2c_add_adapter(i2c_adapter); if (mantis->i2c_rc < 0) return mantis->i2c_rc; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing I2C .."); + dprintk(MANTIS_DEBUG, 1, "Initializing I2C .."); intstat = mmread(MANTIS_INT_STAT); intmask = mmread(MANTIS_INT_MASK); mmwrite(intstat, MANTIS_INT_STAT); mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); - dprintk(verbose, MANTIS_DEBUG, 1, "[0x%08x/%08x]", intstat, intmask); + dprintk(MANTIS_DEBUG, 1, "Status=<%02x> Mask=<%02x>", intstat, intmask); return 0; } +EXPORT_SYMBOL_GPL(mantis_i2c_init); int __devexit mantis_i2c_exit(struct mantis_pci *mantis) { - dprintk(verbose, MANTIS_DEBUG, 1, "Removing I2C adapter"); + dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter"); return i2c_del_adapter(&mantis->adapter); } +EXPORT_SYMBOL_GPL(mantis_i2c_exit); diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h new file mode 100644 index 00000000000..1e49ecfeee3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_i2c.h @@ -0,0 +1,7 @@ +#ifndef __MANTIS_I2C_H +#define __MANTIS_I2C_H + +extern int mantis_i2c_init(struct mantis_pci *mantis); +extern int mantis_i2c_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_I2C_H */ diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c new file mode 100644 index 00000000000..4700088f038 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -0,0 +1,145 @@ +/* + Mantis PCI bridge driver + + Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_ioc.h" + +static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + int err; + struct i2c_msg msg[] = { + { .addr = 0x50, .flags = 0, .buf = data, .len = 1 }, + { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, + }; + + err = i2c_transfer(adapter, msg, 2); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", + err, data[0], data[1]); + + return err; + } + + return 0; +} + +static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +{ + struct i2c_adapter *adapter = &mantis->adapter; + int err; + + struct i2c_msg msg = { .addr = 0x50, .flags = 0, .buf = data, .len = length }; + + err = i2c_transfer(adapter, &msg, 1); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", + err, length, data[0], data[1]); + + return err; + } + + return 0; +} + +int mantis_get_mac(struct mantis_pci *mantis) +{ + int err; + + mantis->mac_address[0] = 0x08; + + err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err); + + return err; + } + + dprintk(MANTIS_ERROR, 0, + " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", + mantis->mac_address[0], mantis->mac_address[1], + mantis->mac_address[2], mantis->mac_address[3], + mantis->mac_address[4], mantis->mac_address[5]); + + return 0; +} +EXPORT_SYMBOL_GPL(mantis_get_mac); + +/* Turn the given bit on or off. */ +void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) +{ + u32 cur; + + cur = mmread(MANTIS_GPIF_ADDR); + if (value) + mantis->gpio_status = cur | (1 << bitpos); + else + mantis->gpio_status = cur & (~(1 << bitpos)); + + mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); + mmwrite(0x00, MANTIS_GPIF_DOUT); +} +EXPORT_SYMBOL_GPL(gpio_set_bits); + +int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl) +{ + u32 reg; + + reg = mmread(MANTIS_CONTROL); + switch (stream_ctl) { + case STREAM_TO_HIF: + dprintk(MANTIS_DEBUG, 1, "Set stream to HIF"); + reg &= 0xff - MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + reg |= MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + break; + + case STREAM_TO_CAM: + dprintk(MANTIS_DEBUG, 1, "Set stream to CAM"); + reg |= MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + reg &= 0xff - MANTIS_BYPASS; + mmwrite(reg, MANTIS_CONTROL); + break; + default: + dprintk(MANTIS_ERROR, 1, "Unknown MODE <%02x>", stream_ctl); + return -1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mantis_stream_control); diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index f9aaaa52f52..f6030c9fba2 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -58,7 +58,6 @@ struct mantis_ca { enum mantis_slot_state slot_state; -// struct dvb_device *ca_dev; void *ca_priv; struct dvb_ca_en50221 en50221; @@ -81,4 +80,4 @@ extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data); extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr); extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data); -#endif // __MANTIS_LINK_H +#endif /* __MANTIS_LINK_H */ diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index d1eac4083fc..5165a390e07 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -18,6 +18,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include #include #include #include @@ -25,264 +28,149 @@ #include #include #include -#include "mantis_common.h" -#include "mantis_core.h" -#include "mantis_uart.h" +#include #include #include #include #include -unsigned int verbose = 1; -module_param(verbose, int, 0644); -MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); - -unsigned int devs; - -#define PCI_VENDOR_ID_MANTIS 0x1822 -#define PCI_DEVICE_ID_MANTIS_R11 0x4e35 -#define DRIVER_NAME "Mantis" - -static struct pci_device_id mantis_pci_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MANTIS, PCI_DEVICE_ID_MANTIS_R11) }, - { 0 }, -}; - -MODULE_DEVICE_TABLE(pci, mantis_pci_table); - -static irqreturn_t mantis_pci_irq(int irq, void *dev_id) -{ - u32 stat = 0, mask = 0, lstat = 0, mstat = 0; - u32 rst_stat = 0, rst_mask = 0; +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" - struct mantis_pci *mantis; - struct mantis_ca *ca; +#include +#include +#include +#include - mantis = (struct mantis_pci *) dev_id; - if (unlikely(mantis == NULL)) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis == NULL"); - return IRQ_NONE; - } - ca = mantis->mantis_ca; - - stat = mmread(MANTIS_INT_STAT); - mask = mmread(MANTIS_INT_MASK); - mstat = lstat = stat & ~MANTIS_INT_RISCSTAT; - if (!(stat & mask)) - return IRQ_NONE; - - rst_mask = MANTIS_GPIF_WRACK | - MANTIS_GPIF_OTHERR | - MANTIS_SBUF_WSTO | - MANTIS_GPIF_EXTIRQ; - - rst_stat = mmread(MANTIS_GPIF_STATUS); - rst_stat &= rst_mask; - mmwrite(rst_stat, MANTIS_GPIF_STATUS); - - mantis->mantis_int_stat = stat; - mantis->mantis_int_mask = mask; - dprintk(verbose, MANTIS_DEBUG, 0, "=== Interrupts[%04x/%04x]= [", stat, mask); - if (stat & MANTIS_INT_RISCEN) { - dprintk(verbose, MANTIS_DEBUG, 0, "* DMA enabl *"); - } - if (stat & MANTIS_INT_IRQ0) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-0 *"); - mantis->gpif_status = rst_stat; - wake_up(&ca->hif_write_wq); - schedule_work(&ca->hif_evm_work); - } - if (stat & MANTIS_INT_IRQ1) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT IRQ-1 *"); - schedule_work(&mantis->uart_work); - } - if (stat & MANTIS_INT_OCERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT OCERR *"); - } - if (stat & MANTIS_INT_PABORT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PABRT *"); - } - if (stat & MANTIS_INT_RIPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RIPRR *"); - } - if (stat & MANTIS_INT_PPERR) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT PPERR *"); - } - if (stat & MANTIS_INT_FTRGT) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT FTRGT *"); - } - if (stat & MANTIS_INT_RISCI) { - dprintk(verbose, MANTIS_DEBUG, 0, "* INT RISCI *"); - mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28; - tasklet_schedule(&mantis->tasklet); - } - if (stat & MANTIS_INT_I2CDONE) { - dprintk(verbose, MANTIS_DEBUG, 0, "* I2C DONE *"); - wake_up(&mantis->i2c_wq); - } - mmwrite(stat, MANTIS_INT_STAT); - stat &= ~(MANTIS_INT_RISCEN | MANTIS_INT_I2CDONE | - MANTIS_INT_I2CRACK | MANTIS_INT_PCMCIA7 | - MANTIS_INT_PCMCIA6 | MANTIS_INT_PCMCIA5 | - MANTIS_INT_PCMCIA4 | MANTIS_INT_PCMCIA3 | - MANTIS_INT_PCMCIA2 | MANTIS_INT_PCMCIA1 | - MANTIS_INT_PCMCIA0 | MANTIS_INT_IRQ1 | - MANTIS_INT_IRQ0 | MANTIS_INT_OCERR | - MANTIS_INT_PABORT | MANTIS_INT_RIPERR | - MANTIS_INT_PPERR | MANTIS_INT_FTRGT | - MANTIS_INT_RISCI); - - if (stat) - dprintk(verbose, MANTIS_DEBUG, 0, "* Unknown [%04x] *", stat); - - dprintk(verbose, MANTIS_DEBUG, 0, "] ===\n"); - - return IRQ_HANDLED; -} +#include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_pci.h" +#define DRIVER_NAME "Mantis Core" -static int __devinit mantis_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *mantis_pci_table) +int __devinit mantis_pci_init(struct mantis_pci *mantis) { u8 revision, latency; - struct mantis_pci *mantis; - int ret = 0; + struct mantis_hwconfig *config = mantis->hwconfig; + struct pci_dev *pdev = mantis->pdev; + int err, ret = 0; + + dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n", + config->model_name, + config->dev_type, + mantis->pdev->bus->number, + PCI_SLOT(mantis->pdev->devfn), + PCI_FUNC(mantis->pdev->devfn)); + + err = pci_enable_device(pdev); + if (err != 0) { + ret = -ENODEV; + dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err); + goto fail0; + } - mantis = kmalloc(sizeof (struct mantis_pci), GFP_KERNEL); - if (mantis == NULL) { - printk("%s: Out of memory\n", __func__); + err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (err != 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err); ret = -ENOMEM; - goto err; + goto fail1; } - memset(mantis, 0, sizeof (struct mantis_pci)); - mantis->num = devs; - devs++; - if (pci_enable_device(pdev)) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis PCI enable failed"); - ret = -ENODEV; - goto err; - } - mantis->mantis_addr = pci_resource_start(pdev, 0); - if (!request_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0), DRIVER_NAME)) { - ret = -ENODEV; - goto err0; - } + pci_set_master(pdev); - mantis->mantis_mmio = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + if (!request_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0), + DRIVER_NAME)) { - if (!mantis->mantis_mmio) { - dprintk(verbose, MANTIS_ERROR, 1, "IO remap failed"); + dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !"); ret = -ENODEV; - goto err1; + goto fail1; } - // Clear and disable all interrupts at startup - // to avoid lockup situations - mmwrite(0x00, MANTIS_INT_MASK); - if (request_irq(pdev->irq, - mantis_pci_irq, - IRQF_SHARED, - DRIVER_NAME, - mantis) < 0) { + mantis->mmio = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); - dprintk(verbose, MANTIS_ERROR, 1, "Mantis IRQ reg failed"); + if (!mantis->mmio) { + dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !"); ret = -ENODEV; - goto err2; + goto fail2; } - pci_set_master(pdev); - pci_set_drvdata(pdev, mantis); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); mantis->latency = latency; mantis->revision = revision; - mantis->pdev = pdev; - mantis->subsystem_vendor = pdev->subsystem_vendor; - mantis->subsystem_device = pdev->subsystem_device; - init_waitqueue_head(&mantis->i2c_wq); - mantis_set_direction(mantis, 0); /* CAM bypass */ + dprintk(MANTIS_ERROR, 0, " Mantis Rev %d [%04x:%04x], ", + mantis->revision, + mantis->pdev->subsystem_vendor, + mantis->pdev->subsystem_device); + + dprintk(MANTIS_ERROR, 0, + "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", + mantis->pdev->irq, + mantis->latency, + mantis->mantis_addr, + mantis->mmio); - if (!latency) - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 32); + err = request_irq(pdev->irq, + config->irq_handler, + IRQF_SHARED, + DRIVER_NAME, + mantis); - dprintk(verbose, MANTIS_ERROR, 0, - "irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p\n", - pdev->irq, mantis->latency, - mantis->mantis_addr, mantis->mantis_mmio); + if (err != 0) { - // No more PCI specific stuff ! - if (mantis_core_init(mantis) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Mantis core init failed"); + dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err); ret = -ENODEV; - goto err2; + goto fail3; } - return 0; + pci_set_drvdata(pdev, mantis); + return ret; - // Error conditions .. -err2: - dprintk(verbose, MANTIS_DEBUG, 1, "Err: IO Unmap"); - if (mantis->mantis_mmio) - iounmap(mantis->mantis_mmio); -err1: - dprintk(verbose, MANTIS_DEBUG, 1, "Err: Release regions"); + /* Error conditions */ +fail3: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret); + if (mantis->mmio) + iounmap(mantis->mmio); + +fail2: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret); release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + pci_resource_len(pdev, 0)); + +fail1: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret); pci_disable_device(pdev); -err0: - dprintk(verbose, MANTIS_DEBUG, 1, "Err: Free"); - kfree(mantis); -err: - dprintk(verbose, MANTIS_DEBUG, 1, "Err:"); + +fail0: + dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret); + pci_set_drvdata(pdev, NULL); return ret; } +EXPORT_SYMBOL_GPL(mantis_pci_init); -static void __devexit mantis_pci_remove(struct pci_dev *pdev) +void __devexit mantis_pci_exit(struct mantis_pci *mantis) { - struct mantis_pci *mantis = pci_get_drvdata(pdev); - - if (mantis == NULL) { - dprintk(verbose, MANTIS_ERROR, 1, "Aeio, Mantis NULL ptr"); - return; - } - mantis_core_exit(mantis); - dprintk(verbose, MANTIS_ERROR, 1, "Removing -->Mantis irq: %d, latency: %d\n memory: 0x%lx, mmio: 0x%p", - pdev->irq, mantis->latency, mantis->mantis_addr, - mantis->mantis_mmio); + struct pci_dev *pdev = mantis->pdev; + dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio); free_irq(pdev->irq, mantis); - pci_release_regions(pdev); - if (mantis_dma_exit(mantis) < 0) - dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed"); + if (mantis->mmio) { + iounmap(mantis->mmio); + release_mem_region(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + } - pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); - kfree(mantis); -} - -static struct pci_driver mantis_pci_driver = { - .name = DRIVER_NAME, - .id_table = mantis_pci_table, - .probe = mantis_pci_probe, - .remove = mantis_pci_remove, -}; - -static int __devinit mantis_pci_init(void) -{ - return pci_register_driver(&mantis_pci_driver); -} - -static void __devexit mantis_pci_exit(void) -{ - pci_unregister_driver(&mantis_pci_driver); + pci_set_drvdata(pdev, NULL); } - -module_init(mantis_pci_init); -module_exit(mantis_pci_exit); +EXPORT_SYMBOL_GPL(mantis_pci_exit); MODULE_DESCRIPTION("Mantis PCI DTV bridge driver"); MODULE_AUTHOR("Manu Abraham"); diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h new file mode 100644 index 00000000000..5ce776ffcb3 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_pci.h @@ -0,0 +1,7 @@ +#ifndef __MANTIS_PCI_H +#define __MANTIS_PCI_H + +extern int mantis_pci_init(struct mantis_pci *mantis); +extern void mantis_pci_exit(struct mantis_pci *mantis); + +#endif /* __MANTIS_PCI_H */ diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 4156a082088..90ca356985e 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -18,8 +18,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" #include "mantis_link.h" /* temporary due to physical layer stuff */ +#include "mantis_reg.h" /* * If Slot state is already PLUG_IN event and we are called @@ -32,7 +46,7 @@ void mantis_event_cam_plugin(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_XTRACTED) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0xda000000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -56,7 +70,7 @@ void mantis_event_cam_unplug(struct mantis_ca *ca) u32 gpif_irqcfg; if (ca->slot_state == MODULE_INSERTED) { - dprintk(verbose, MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num); udelay(50); mmwrite(0x00da0000, MANTIS_CARD_RESET); gpif_irqcfg = mmread(MANTIS_GPIF_IRQCFG); @@ -80,14 +94,14 @@ int mantis_pcmcia_init(struct mantis_ca *ca) card_stat = mmread(MANTIS_GPIF_IRQCFG); if (gpif_stat & MANTIS_GPIF_DETSTAT) { - dprintk(verbose, MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_INSERTED; dvb_ca_en50221_camchange_irq(&ca->en50221, 0, DVB_CA_EN50221_CAMCHANGE_INSERTED); } else { - dprintk(verbose, MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); + dprintk(MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num); mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG); ca->slot_state = MODULE_XTRACTED; dvb_ca_en50221_camchange_irq(&ca->en50221, diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index 6f5cd493676..0072e149a56 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -21,7 +21,7 @@ #ifndef __MANTIS_REG_H #define __MANTIS_REG_H -// Interrupts +/* Interrupts */ #define MANTIS_INT_STAT 0x00 #define MANTIS_INT_MASK 0x04 @@ -49,8 +49,12 @@ #define MANTIS_INT_RISCI (0x01 << 1) #define MANTIS_INT_I2CDONE (0x01 << 0) -// DMA +/* DMA */ #define MANTIS_DMA_CTL 0x08 +#define MANTIS_GPIF_RD (0xff << 24) +#define MANTIS_GPIF_WR (0xff << 16) +#define MANTIS_CPU_DO (0x01 << 10) +#define MANTIS_DRV_DO (0x01 << 9) #define MANTIS_I2C_RD (0x01 << 7) #define MANTIS_I2C_WR (0x01 << 6) #define MANTIS_DCAP_MODE (0x01 << 5) @@ -61,10 +65,16 @@ #define MANTIS_DCAP_EN (0x01 << 1) #define MANTIS_RISC_EN (0x01 << 0) +/* DEBUG */ +#define MANTIS_DEBUGREG 0x0c +#define MANTIS_DATINV (0x0e << 7) +#define MANTIS_TOP_DEBUGSEL (0x07 << 4) +#define MANTIS_PCMCIA_DEBUGSEL (0x0f << 0) + #define MANTIS_RISC_START 0x10 #define MANTIS_RISC_PC 0x14 -// I2C +/* I2C */ #define MANTIS_I2CDATA_CTL 0x18 #define MANTIS_I2C_RATE_1 (0x00 << 6) #define MANTIS_I2C_RATE_2 (0x01 << 6) @@ -73,6 +83,28 @@ #define MANTIS_I2C_STOP (0x01 << 5) #define MANTIS_I2C_PGMODE (0x01 << 3) +/* DATA */ +#define MANTIS_CMD_DATA_R1 0x20 +#define MANTIS_CMD_DATA_3 (0xff << 24) +#define MANTIS_CMD_DATA_2 (0xff << 16) +#define MANTIS_CMD_DATA_1 (0xff << 8) +#define MANTIS_CMD_DATA_0 (0xff << 0) + +#define MANTIS_CMD_DATA_R2 0x24 +#define MANTIS_CMD_DATA_7 (0xff << 24) +#define MANTIS_CMD_DATA_6 (0xff << 16) +#define MANTIS_CMD_DATA_5 (0xff << 8) +#define MANTIS_CMD_DATA_4 (0xff << 0) + +#define MANTIS_CONTROL 0x28 +#define MANTIS_DET (0x01 << 7) +#define MANTIS_DAT_CF_EN (0x01 << 6) +#define MANTIS_ACS (0x03 << 4) +#define MANTIS_VCCEN (0x01 << 3) +#define MANTIS_BYPASS (0x01 << 2) +#define MANTIS_MRST (0x01 << 1) +#define MANTIS_CRST_INT (0x01 << 0) + #define MANTIS_GPIF_CFGSLA 0x84 #define MANTIS_GPIF_WAITSMPL (0x07 << 28) #define MANTIS_GPIF_BYTEADDRSUB (0x01 << 25) @@ -162,4 +194,4 @@ #define MANTIS_GPIF_LOGICRD (0xffff << 16) #define MANTIS_GPIF_LOGICRW (0xffff << 0) -#endif //__MANTIS_REG_H +#endif /* __MANTIS_REG_H */ diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index 786fcc33911..fb423b0a58f 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -1,5 +1,20 @@ +#include #include + +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_uart.h" struct mantis_uart_params { enum mantis_baud baud_rate; @@ -18,20 +33,20 @@ int mantis_uart_read(struct mantis_pci *mantis, u8 *data) for (i = 0; i < (config->bytes + 1); i++) { if (stat & MANTIS_UART_RXFIFO_FULL) { - dprintk(verbose, MANTIS_ERROR, 1, "RX Fifo FULL"); + dprintk(MANTIS_ERROR, 1, "RX Fifo FULL"); } data[i] = mmread(MANTIS_UART_RXD) & 0x3f; stat = mmread(MANTIS_UART_STAT); - dprintk(verbose, MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); + dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); if (data[i] & (1 << 7)) { - dprintk(verbose, MANTIS_ERROR, 1, "UART framing error"); + dprintk(MANTIS_ERROR, 1, "UART framing error"); return -EINVAL; } if (data[i] & (1 << 6)) { - dprintk(verbose, MANTIS_ERROR, 1, "UART parity error"); + dprintk(MANTIS_ERROR, 1, "UART parity error"); return -EINVAL; } } @@ -46,14 +61,14 @@ static void mantis_uart_work(struct work_struct *work) u8 buf[16]; int i; - dprintk(verbose, MANTIS_DEBUG, 1, "UART read"); + dprintk(MANTIS_DEBUG, 1, "UART read"); mantis_uart_read(mantis, buf); - dprintk(verbose, MANTIS_DEBUG, 1, "UART: "); + dprintk(MANTIS_DEBUG, 1, "UART: "); for (i = 0; i < (config->bytes + 1); i++) - dprintk(verbose, MANTIS_DEBUG, 0, "<%02x> ", buf[i]); + dprintk(MANTIS_DEBUG, 0, "<%02x> ", buf[i]); - dprintk(verbose, MANTIS_DEBUG, 0, "\n"); + dprintk(MANTIS_DEBUG, 0, "\n"); } static int mantis_uart_setup(struct mantis_pci *mantis, @@ -64,7 +79,7 @@ static int mantis_uart_setup(struct mantis_pci *mantis, u32 reg; - dprintk(verbose, MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", + dprintk(MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", parity[params->parity], rates[params->baud_rate]); @@ -102,7 +117,7 @@ int mantis_uart_init(struct mantis_pci *mantis) struct mantis_hwconfig *config = mantis->hwconfig; struct mantis_uart_params params; - dprintk(verbose, MANTIS_DEBUG, 1, "Initializing UART .."); + dprintk(MANTIS_DEBUG, 1, "Initializing UART .."); /* default parity: */ params.baud_rate = config->baud_rate; params.parity = config->parity; @@ -131,9 +146,11 @@ int mantis_uart_init(struct mantis_pci *mantis) return 0; } +EXPORT_SYMBOL_GPL(mantis_uart_init); void mantis_uart_exit(struct mantis_pci *mantis) { /* disable interrupt */ mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL); } +EXPORT_SYMBOL_GPL(mantis_uart_exit); diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index e9f938d37c3..0a42cd01ab2 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -56,4 +56,4 @@ struct mantis_pci; extern int mantis_uart_init(struct mantis_pci *mantis); extern void mantis_uart_exit(struct mantis_pci *mantis); -#endif // __MANTIS_UART_H +#endif /* __MANTIS_UART_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 64cdfb8b709..f2092ce9c4b 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -18,6 +18,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "stv0299.h" #include "mantis_common.h" #include "mantis_vp1033.h" @@ -66,47 +78,21 @@ u8 lgtdqcs001f_inittab[] = { 0xff, 0xff, }; -struct stv0299_config lgtdqcs001f_config = { - .demod_address = 0x68, - .inittab = lgtdqcs001f_inittab, - .mclk = 88000000UL, -// .invert = 0, - .invert = 1, -// .enhanced_tuning = 0, - .skip_reinit = 0, -// .lock_output = STV0229_LOCKOUTPUT_0, - .volt13_op0_op1 = STV0299_VOLT13_OP0, - .min_delay_ms = 100, - .set_symbol_rate = lgtdqcs001f_set_symbol_rate, -// .pll_set = lgtdqcs001f_pll_set, -}; - #define MANTIS_MODEL_NAME "VP-1033" #define MANTIS_DEV_TYPE "DVB-S/DSS" -struct mantis_hwconfig vp1033_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_204, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { + struct mantis_pci *mantis = fe->dvb->priv; + struct i2c_adapter *adapter = &mantis->adapter; + u8 buf[4]; u32 div; - struct mantis_pci *mantis = fe->dvb->priv; - struct i2c_msg msg = { - .addr = 0x61, - .flags = 0, - .buf = buf, - .len = sizeof (buf) - }; + struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof (buf) }; + div = params->frequency / 250; buf[0] = (div >> 8) & 0x7f; @@ -118,8 +104,8 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, buf[3] |= 0x04; else buf[3] &= ~0x04; - if (i2c_transfer(&mantis->adapter, &msg, 1) < 0) { - dprintk(verbose, MANTIS_ERROR, 1, "Write: I2C Transfer failed"); + if (i2c_transfer(adapter, &msg, 1) < 0) { + dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed"); return -EIO; } msleep_interruptible(100); @@ -161,3 +147,49 @@ int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, return 0; } + +struct stv0299_config lgtdqcs001f_config = { + .demod_address = 0x68, + .inittab = lgtdqcs001f_inittab, + .mclk = 88000000UL, + .invert = 0, + .skip_reinit = 0, + .volt13_op0_op1 = STV0299_VOLT13_OP0, + .min_delay_ms = 100, + .set_symbol_rate = lgtdqcs001f_set_symbol_rate, +}; + +static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + fe = stv0299_attach(&lgtdqcs001f_config, adapter); + + if (fe) { + fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp1033_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp1033_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h index e24570659d5..2c18d215324 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -21,19 +21,10 @@ #ifndef __MANTIS_VP1033_H #define __MANTIS_VP1033_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "stv0299.h" #define MANTIS_VP_1033_DVB_S 0x0016 -extern struct stv0299_config lgtdqcs001f_config; -extern struct mantis_hwconfig vp1033_mantis_config; +extern struct mantis_hwconfig vp1033_config; -extern int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params); - -extern int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio); - - -#endif // __MANTIS_VP1033_H +#endif /* __MANTIS_VP1033_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 28f3420b231..40778ec8f46 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -18,10 +18,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mb86a16.h" #include "mantis_common.h" +#include "mantis_ioc.h" #include "mantis_vp1034.h" +#include "mantis_reg.h" -struct mb86a16_config vp1034_config = { +struct mb86a16_config vp1034_mb86a16_config = { .demod_address = 0x08, .set_voltage = vp1034_set_voltage, }; @@ -29,38 +43,62 @@ struct mb86a16_config vp1034_config = { #define MANTIS_MODEL_NAME "VP-1034" #define MANTIS_DEV_TYPE "DVB-S/DSS" -struct mantis_hwconfig vp1034_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_204, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct mantis_pci *mantis = fe->dvb->priv; switch (voltage) { case SEC_VOLTAGE_13: - dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[13V]"); + dprintk(MANTIS_ERROR, 1, "Polarization=[13V]"); gpio_set_bits(mantis, 13, 1); gpio_set_bits(mantis, 14, 0); break; case SEC_VOLTAGE_18: - dprintk(verbose, MANTIS_ERROR, 1, "Polarization=[18V]"); + dprintk(MANTIS_ERROR, 1, "Polarization=[18V]"); gpio_set_bits(mantis, 13, 1); gpio_set_bits(mantis, 14, 1); break; case SEC_VOLTAGE_OFF: - dprintk(verbose, MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); + dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); break; default: - dprintk(verbose, MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); return -EINVAL; } mmwrite(0x00, MANTIS_GPIF_DOUT); return 0; } + +static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_mb86a16_config.demod_address); + + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp1034_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp1034_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h index 21948573b08..30269129066 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -23,13 +23,11 @@ #include "dvb_frontend.h" #include "mantis_common.h" -#include "mb86a16.h" #define MANTIS_VP_1034_DVB_S 0x0014 -extern struct mantis_hwconfig vp1034_mantis_config; -extern struct mb86a16_config vp1034_config; +extern struct mantis_hwconfig vp1034_config; extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage); -#endif // __MANTIS_VP1034_H +#endif /* __MANTIS_VP1034_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 90df80b80e1..1181fad3b27 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -18,24 +18,31 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp1041.h" #include "stb0899_reg.h" +#include "stb0899_drv.h" #include "stb0899_cfg.h" #include "stb6100_cfg.h" +#include "stb6100.h" +#include "lnbp21.h" #define MANTIS_MODEL_NAME "VP-1041" #define MANTIS_DEV_TYPE "DSS/DVB-S/DVB-S2" -struct mantis_hwconfig vp1041_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_188, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { // 0x0000000b , /* SYSREG */ @@ -258,7 +265,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = { { 0xffff , 0xff }, }; -struct stb0899_config vp1041_config = { +struct stb0899_config vp1041_stb0899_config = { .init_dev = vp1041_stb0899_s1_init_1, .init_s2_demod = stb0899_s2_init_2, .init_s1_demod = vp1041_stb0899_s1_init_3, @@ -299,3 +306,55 @@ struct stb6100_config vp1041_stb6100_config = { .tuner_address = 0x60, .refclock = 27000000, }; + +static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + int err = 0; + + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter); + if (mantis->fe) { + dprintk(MANTIS_ERROR, 1, + "found STB0899 DVB-S/DVB-S2 frontend @0x%02x", + vp1041_stb0899_config.demod_address); + + if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) { + if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) { + printk("%s: No LNBP21 found!\n", __func__); + } + } + } else { + return -EREMOTEIO; + } + } else { + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; + } + + + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp1041_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp1041_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h index 2cc83a6e599..1ae5b3de808 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.h +++ b/drivers/media/dvb/mantis/mantis_vp1041.h @@ -21,17 +21,13 @@ #ifndef __MANTIS_VP1041_H #define __MANTIS_VP1041_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "stb0899_drv.h" -#include "stb6100.h" -#include "lnbp21.h" #define MANTIS_VP_1041_DVB_S2 0x0031 -#define TECHNISAT_SKYSTAR_HD2 0x0001 +#define SKYSTAR_HD2_10 0x0001 +#define SKYSTAR_HD2_20 0x0003 +#define CINERGY_S2_PCI_HD 0x1179 -extern struct mantis_hwconfig vp1041_mantis_config; -extern struct stb0899_config vp1041_config; -extern struct stb6100_config vp1041_stb6100_config; +extern struct mantis_hwconfig vp1041_config; -#endif // __MANTIS_VP1041_H +#endif /* __MANTIS_VP1041_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 1171e69b7e6..877329175d0 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -18,48 +18,59 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "tda1002x.h" #include "mantis_common.h" #include "mantis_vp2033.h" #define MANTIS_MODEL_NAME "VP-2033" #define MANTIS_DEV_TYPE "DVB-C" -struct mantis_hwconfig vp2033_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_204, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, +struct tda1002x_config vp2033_tda1002x_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, }; -struct tda1002x_config philips_cu1216_config = { +struct tda10023_config vp2033_tda10023_cu1216_config = { .demod_address = 0x18 >> 1, .invert = 1, }; -u8 read_pwm(struct mantis_pci *mantis) +static u8 read_pwm(struct mantis_pci *mantis) { + struct i2c_adapter *adapter = &mantis->adapter; + u8 b = 0xff; u8 pwm; struct i2c_msg msg[] = { - {.addr = 0x50,.flags = 0,.buf = &b,.len = 1}, - {.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} + {.addr = 0x50, .flags = 0, .buf = &b, .len = 1}, + {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1} }; - if ((i2c_transfer(&mantis->adapter, msg, 2) != 2) + if ((i2c_transfer(adapter, msg, 2) != 2) || (pwm == 0xff)) pwm = 0x48; return pwm; } -int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { struct mantis_pci *mantis = fe->dvb->priv; + struct i2c_adapter *adapter = &mantis->adapter; u8 buf[6]; - struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) }; + struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof (buf) }; int i; #define CU1216_IF 36125000 @@ -78,7 +89,7 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parame if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) + if (i2c_transfer(adapter, &msg, 1) != 1) return -EIO; /* wait for the pll lock */ @@ -88,7 +99,7 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parame if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&mantis->adapter, &msg, 1) == 1 && (buf[0] & 0x40)) + if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40)) break; msleep(10); @@ -102,8 +113,58 @@ int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parame if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); - if (i2c_transfer(&mantis->adapter, &msg, 1) != 1) + if (i2c_transfer(adapter, &msg, 1) != 1) return -EIO; return 0; } + +static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", + vp2033_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2033_tda1002x_cu1216_config.demod_address); + } + } + + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_DEBUG, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp2033_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_204, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp2033_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index fcf8b85be94..e6c5fe80f72 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -21,17 +21,10 @@ #ifndef __MANTIS_VP2033_H #define __MANTIS_VP2033_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "tda1002x.h" #define MANTIS_VP_2033_DVB_C 0x0008 -extern struct tda1002x_config philips_cu1216_config; -extern struct mantis_hwconfig vp2033_mantis_config; +extern struct mantis_hwconfig vp2033_config; -extern int philips_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params); - -extern u8 read_pwm(struct mantis_pci *mantis); - -#endif // __MANTIS_VP2033_H +#endif /* __MANTIS_VP2033_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index ce73d6beb5c..51b082f7f91 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -18,22 +18,153 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "tda1002x.h" #include "mantis_common.h" #include "mantis_vp2040.h" #define MANTIS_MODEL_NAME "VP-2040" #define MANTIS_DEV_TYPE "DVB-C" -struct mantis_hwconfig vp2040_mantis_config = { +struct tda1002x_config vp2040_tda1002x_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, +}; + +struct tda10023_config vp2040_tda10023_cu1216_config = { + .demod_address = 0x18 >> 1, + .invert = 1, +}; + +static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct mantis_pci *mantis = fe->dvb->priv; + struct i2c_adapter *adapter = &mantis->adapter; + + u8 buf[6]; + struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof (buf) }; + int i; + +#define CU1216_IF 36125000 +#define TUNER_MUL 62500 + + u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL; + + buf[0] = (div >> 8) & 0x7f; + buf[1] = div & 0xff; + buf[2] = 0xce; + buf[3] = (params->frequency < 150000000 ? 0x01 : + params->frequency < 445000000 ? 0x02 : 0x04); + buf[4] = 0xde; + buf[5] = 0x20; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(adapter, &msg, 1) != 1) + return -EIO; + + /* wait for the pll lock */ + msg.flags = I2C_M_RD; + msg.len = 1; + for (i = 0; i < 20; i++) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40)) + break; + + msleep(10); + } + + /* switch the charge pump to the lower current */ + msg.flags = 0; + msg.len = 2; + msg.buf = &buf[2]; + buf[2] &= ~0x40; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(adapter, &msg, 1) != 1) + return -EIO; + + return 0; +} + +static u8 read_pwm(struct mantis_pci *mantis) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + u8 b = 0xff; + u8 pwm; + struct i2c_msg msg[] = { + {.addr = 0x50, .flags = 0, .buf = &b, .len = 1}, + {.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1} + }; + + if ((i2c_transfer(adapter, msg, 2) != 2) + || (pwm == 0xff)) + pwm = 0x48; + + return pwm; +} + +static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", + vp2040_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2040_tda1002x_cu1216_config.demod_address); + } + } + + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } + + mantis->fe = fe; + dprintk(MANTIS_DEBUG, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp2040_config = { .model_name = MANTIS_MODEL_NAME, .dev_type = MANTIS_DEV_TYPE, .ts_size = MANTIS_TS_204, + .baud_rate = MANTIS_BAUD_9600, .parity = MANTIS_PARITY_NONE, .bytes = 0, -}; -struct tda10023_config tda10023_cu1216_config = { - .demod_address = 0x18 >> 1, - .invert = 1, + .frontend_init = vp2040_frontend_init, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h index c7457543d8b..d125e219b68 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.h +++ b/drivers/media/dvb/mantis/mantis_vp2040.h @@ -21,15 +21,12 @@ #ifndef __MANTIS_VP2040_H #define __MANTIS_VP2040_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "tda1002x.h" #define MANTIS_VP_2040_DVB_C 0x0043 -#define TERRATEC_CINERGY_C_PCI 0x1178 -#define TECHNISAT_CABLESTAR_HD2 0x0002 +#define CINERGY_C 0x1178 +#define CABLESTAR_HD2 0x0002 -extern struct tda10023_config tda10023_cu1216_config; -extern struct mantis_hwconfig vp2040_mantis_config; +extern struct mantis_hwconfig vp2040_config; -#endif //__MANTIS_VP2040_H +#endif /* __MANTIS_VP2040_H */ diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 9ca8040489d..4b974eeefa9 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -18,6 +18,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "zl10353.h" #include "mantis_common.h" #include "mantis_vp3030.h" @@ -28,15 +40,6 @@ struct zl10353_config mantis_vp3030_config = { #define MANTIS_MODEL_NAME "VP-3030" #define MANTIS_DEV_TYPE "DVB-T" -struct mantis_hwconfig vp3030_mantis_config = { - .model_name = MANTIS_MODEL_NAME, - .dev_type = MANTIS_DEV_TYPE, - .ts_size = MANTIS_TS_188, - .baud_rate = MANTIS_BAUD_9600, - .parity = MANTIS_PARITY_NONE, - .bytes = 0, -}; - int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { @@ -63,3 +66,31 @@ int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, return 0; } + +static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) +{ + struct i2c_adapter *adapter = &mantis->adapter; + + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&mantis_vp3030_config, adapter); + + if (!fe) + return -1; + + mantis->fe = fe; + dprintk(MANTIS_ERROR, 1, "Done!"); + + return 0; +} + +struct mantis_hwconfig vp3030_config = { + .model_name = MANTIS_MODEL_NAME, + .dev_type = MANTIS_DEV_TYPE, + .ts_size = MANTIS_TS_188, + + .baud_rate = MANTIS_BAUD_9600, + .parity = MANTIS_PARITY_NONE, + .bytes = 0, + + .frontend_init = vp3030_frontend_init, +}; diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h index acc50a48e18..0a110ba5c1d 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -21,14 +21,10 @@ #ifndef __MANTIS_VP3030_H #define __MANTIS_VP3030_H -#include "dvb_frontend.h" #include "mantis_common.h" -#include "dvb-pll.h" -#include "zl10353.h" #define MANTIS_VP_3030_DVB_T 0x0024 -extern struct zl10353_config mantis_vp3030_config; -extern struct mantis_hwconfig vp3030_mantis_config; +extern struct mantis_hwconfig vp3030_config; -#endif // __MANTIS_VP3030_H +#endif /* __MANTIS_VP3030_H */ -- cgit v1.2.3 From ad0ac434cb3b34640a4e81d7e80a1512c6e40253 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:41:52 -0300 Subject: V4L/DVB (13796): [Mantis] Add missing file in previous commit Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_ioc.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 drivers/media/dvb/mantis/mantis_ioc.h (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h new file mode 100644 index 00000000000..20526406723 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_ioc.h @@ -0,0 +1,31 @@ +#ifndef __MANTIS_IOC_H +#define __MANTIS_IOC_H + +#define GPIF_A00 0x00 +#define GPIF_A01 0x01 +#define GPIF_A02 0x02 +#define GPIF_A03 0x03 +#define GPIF_A04 0x04 +#define GPIF_A05 0x05 +#define GPIF_A06 0x06 +#define GPIF_A07 0x07 +#define GPIF_A08 0x08 +#define GPIF_A09 0x09 +#define GPIF_A10 0x0a +#define GPIF_A11 0x0b + +#define GPIF_A12 0x0c +#define GPIF_A13 0x0d +#define GPIF_A14 0x0e + +enum mantis_stream_control { + STREAM_TO_HIF = 0, + STREAM_TO_CAM +}; + +extern int mantis_get_mac(struct mantis_pci *mantis); +extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value); + +extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl); + +#endif /* __MANTIS_IOC_H */ -- cgit v1.2.3 From 3e978a8284080d801d20cda377d9cf7c12fe68b9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:56:35 -0300 Subject: V4L/DVB (13797): [Mantis/Hopper/TDA665x] Large overhaul, * Initial go at VP-3028, VP-3030 devices. * I2C communication improvements, * Add TDA665x support Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/Kconfig | 11 ++ drivers/media/dvb/frontends/Makefile | 1 + drivers/media/dvb/frontends/tda665x.c | 257 +++++++++++++++++++++++++++++++ drivers/media/dvb/frontends/tda665x.h | 52 +++++++ drivers/media/dvb/mantis/hopper_cards.c | 1 - drivers/media/dvb/mantis/mantis_cards.c | 11 +- drivers/media/dvb/mantis/mantis_dma.c | 3 +- drivers/media/dvb/mantis/mantis_dvb.c | 22 ++- drivers/media/dvb/mantis/mantis_i2c.c | 141 +++++++++++------ drivers/media/dvb/mantis/mantis_i2c.h | 3 + drivers/media/dvb/mantis/mantis_ioc.c | 42 ++--- drivers/media/dvb/mantis/mantis_vp3030.c | 52 +++---- 12 files changed, 479 insertions(+), 117 deletions(-) create mode 100644 drivers/media/dvb/frontends/tda665x.c create mode 100644 drivers/media/dvb/frontends/tda665x.h (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index a3b8b697349..7820ca084b1 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -587,6 +587,17 @@ config DVB_ATBM8830 help A DMB-TH tuner module. Say Y when you want to support this frontend. +config DVB_TDA665x + tristate "TDA665x tuner" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + Support for tuner modules based on Philips TDA6650/TDA6651 chips. + Say Y when you want to support this chip. + + Currently supported tuners: + * Panasonic ENV57H12D5 (ET-50DT) + comment "Tools to develop new frontends" config DVB_DUMMY_FE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 47575cc7b69..59f7b880355 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_DVB_TDA10048) += tda10048.o obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o obj-$(CONFIG_DVB_S5H1411) += s5h1411.o obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o +obj-$(CONFIG_DVB_TDA665x) += tda665x.o obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c new file mode 100644 index 00000000000..0732a2d38e1 --- /dev/null +++ b/drivers/media/dvb/frontends/tda665x.c @@ -0,0 +1,257 @@ +/* + TDA665x tuner driver + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "dvb_frontend.h" +#include "tda665x.h" + +struct tda665x_state { + struct dvb_frontend *fe; + struct i2c_adapter *i2c; + const struct tda665x_config *config; + + u32 frequency; + u32 bandwidth; +}; + +static int tda665x_read(struct tda665x_state *state, u8 *buf) +{ + const struct tda665x_config *config = state->config; + int err = 0; + struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 }; + + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) + goto exit; + + return err; +exit: + printk("%s: I/O Error err=<%d>\n", __func__, err); + return err; +} + +static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length) +{ + const struct tda665x_config *config = state->config; + int err = 0; + struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length }; + + err = i2c_transfer(state->i2c, &msg, 1); + if (err != 1) + goto exit; + + return err; +exit: + printk("%s: I/O Error err=<%d>\n", __func__, err); + return err; +} + +static int tda665x_get_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *tstate) +{ + struct tda665x_state *state = fe->tuner_priv; + int err = 0; + + switch (param) { + case DVBFE_TUNER_FREQUENCY: + tstate->frequency = state->frequency; + break; + case DVBFE_TUNER_BANDWIDTH: + break; + default: + printk("%s: Unknown parameter (param=%d)\n", __func__, param); + err = -EINVAL; + break; + } + + return err; +} + +static int tda665x_get_status(struct dvb_frontend *fe, u32 *status) +{ + struct tda665x_state *state = fe->tuner_priv; + u8 result = 0; + int err = 0; + + *status = 0; + + err = tda665x_read(state, &result); + if (err < 0) + goto exit; + + if ((result >> 6) & 0x01) { + printk("%s: Tuner Phase Locked\n", __func__); + *status = 1; + } + + return err; +exit: + printk("%s: I/O Error\n", __func__); + return err; +} + +static int tda665x_set_state(struct dvb_frontend *fe, + enum tuner_param param, + struct tuner_state *tstate) +{ + struct tda665x_state *state = fe->tuner_priv; + const struct tda665x_config *config = state->config; + u32 frequency, status = 0; + u8 buf[4]; + int err = 0; + + if (param & DVBFE_TUNER_FREQUENCY) { + + frequency = tstate->frequency; + if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) { + printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); + return -EINVAL; + } + + frequency += config->frequency_offst; + frequency *= config->ref_multiplier; + frequency += config->ref_divider >> 1; + frequency /= config->ref_divider; + + buf[0] = (u8 ) (frequency & 0x7f00) >> 8; + buf[1] = (u8 ) (frequency & 0x00ff) >> 0; + buf[2] = 0x80 | 0x40 | 0x02; + buf[3] = 0x00; + + /* restore frequency */ + frequency = tstate->frequency; + + if (frequency < 153000000) { + /* VHF-L */ + buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */ + if (frequency < 68000000) + buf[3] |= 0x40; /* 83uA */ + if (frequency < 1040000000) + buf[3] |= 0x60; /* 122uA */ + if (frequency < 1250000000) + buf[3] |= 0x80; /* 163uA */ + else + buf[3] |= 0xa0; /* 254uA */ + } else if (frequency < 438000000) { + /* VHF-H */ + buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */ + if (frequency < 230000000) + buf[3] |= 0x40; + if (frequency < 300000000) + buf[3] |= 0x60; + else + buf[3] |= 0x80; + } else { + /* UHF */ + buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */ + if (frequency < 470000000) + buf[3] |= 0x60; + if (frequency < 526000000) + buf[3] |= 0x80; + else + buf[3] |= 0xa0; + } + + /* Set params */ + err = tda665x_write(state, buf, 5); + if (err < 0) + goto exit; + + /* sleep for some time */ + printk("%s: Waiting to Phase LOCK\n", __func__); + msleep(20); + /* check status */ + err = tda665x_get_status(fe, &status); + if (err < 0) + goto exit; + + if (status == 1) { + printk("%s: Tuner Phase locked: status=%d\n", __func__, status); + state->frequency = frequency; /* cache successful state */ + } else { + printk("%s: No Phase lock: status=%d\n", __func__, status); + } + } else { + printk("%s: Unknown parameter (param=%d)\n", __func__, param); + return -EINVAL; + } + + return 0; +exit: + printk("%s: I/O Error\n", __func__); + return err; +} + +static int tda665x_release(struct dvb_frontend *fe) +{ + struct tda665x_state *state = fe->tuner_priv; + + fe->tuner_priv = NULL; + kfree(state); + return 0; +} + +static struct dvb_tuner_ops tda665x_ops = { + + .set_state = tda665x_set_state, + .get_state = tda665x_get_state, + .get_status = tda665x_get_status, + .release = tda665x_release +}; + +struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, + const struct tda665x_config *config, + struct i2c_adapter *i2c) +{ + struct tda665x_state *state = NULL; + struct dvb_tuner_info *info; + + state = kzalloc(sizeof (struct tda665x_state), GFP_KERNEL); + if (state == NULL) + goto exit; + + state->config = config; + state->i2c = i2c; + state->fe = fe; + fe->tuner_priv = state; + fe->ops.tuner_ops = tda665x_ops; + info = &fe->ops.tuner_ops.info; + + memcpy(info->name, config->name, sizeof (config->name)); + info->frequency_min = config->frequency_min; + info->frequency_max = config->frequency_max; + info->frequency_step = config->frequency_offst; + + printk("%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); + + return fe; + +exit: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(tda665x_attach); + +MODULE_DESCRIPTION("TDA665x driver"); +MODULE_AUTHOR("Manu Abraham"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h new file mode 100644 index 00000000000..c0b544d8ef5 --- /dev/null +++ b/drivers/media/dvb/frontends/tda665x.h @@ -0,0 +1,52 @@ +/* + TDA665x tuner driver + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __TDA665x_H +#define __TDA665x_H + +struct tda665x_config { + char name[128]; + + u8 addr; + u32 frequency_min; + u32 frequency_max; + u32 frequency_offst; + u32 ref_multiplier; + u32 ref_divider; +}; + +#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE)) + +extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, + const struct tda665x_config *config, + struct i2c_adapter *i2c); + +#else + +static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, + const struct tda665x_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_TDA665x */ + +#endif /* __TDA665x_H */ diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 749e3f3dd06..01a9ff07d77 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -219,7 +219,6 @@ static void __devexit hopper_pci_remove(struct pci_dev *pdev) struct mantis_pci *mantis = pci_get_drvdata(pdev); if (mantis) { -// mantis_uart_exit(mantis); mantis_dvb_exit(mantis); mantis_dma_exit(mantis); mantis_i2c_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index d486c7fcb45..638177ce72a 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -50,7 +50,6 @@ static char *label[10] = { "RACK" }; - static irqreturn_t mantis_irq_handler(int irq, void *dev_id) { u32 stat = 0, mask = 0, lstat = 0, mstat = 0; @@ -199,6 +198,14 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev return err; +fail7: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); + mantis_uart_exit(mantis); + +fail6: + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis CA exit! <%d>", err); + mantis_ca_exit(mantis); + fail5: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); mantis_dvb_exit(mantis); @@ -228,8 +235,6 @@ static void __devexit mantis_pci_remove(struct pci_dev *pdev) struct mantis_pci *mantis = pci_get_drvdata(pdev); if (mantis) { - mantis_uart_exit(mantis); -// mantis_ca_exit(mantis); mantis_dvb_exit(mantis); mantis_dma_exit(mantis); mantis_i2c_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index 8ebcd96b2b7..eab3645f7ac 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -153,8 +153,7 @@ int mantis_dma_init(struct mantis_pci *mantis) if (mantis_alloc_buffers(mantis) < 0) { dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); - // Stop RISC Engine -// mmwrite(mmread(MANTIS_DMA_CTL) & ~MANTIS_RISC_EN, MANTIS_DMA_CTL); + /* Stop RISC Engine */ mmwrite(0, MANTIS_DMA_CTL); goto err; diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index be911d76daa..42f658b06a6 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -252,14 +252,19 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) err5: tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); + err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); + err3: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + err2: dvb_dmxdev_release(&mantis->dmxdev); + err1: dvb_dmx_release(&mantis->demux); + err0: dvb_unregister_adapter(&mantis->dvb_adapter); @@ -271,21 +276,24 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) { int err; - err = mantis_frontend_shutdown(mantis); - if (err != 0) - dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); + if (mantis->fe) { +// mantis_ca_exit(mantis); + err = mantis_frontend_shutdown(mantis); + if (err != 0) + dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); + + dvb_unregister_frontend(mantis->fe); + } -// mantis_ca_exit(mantis); tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); + mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw); + dvb_dmxdev_release(&mantis->dmxdev); dvb_dmx_release(&mantis->demux); - if (mantis->fe) - dvb_unregister_frontend(mantis->fe); - dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter"); dvb_unregister_adapter(&mantis->dvb_adapter); diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index ba55f0a9a10..16b9e7e77b8 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -35,38 +35,9 @@ #define I2C_HW_B_MANTIS 0x1c -static int mantis_ack_wait(struct mantis_pci *mantis) -{ - int rc = 0; - u32 timeout = 0; - - if (wait_event_timeout(mantis->i2c_wq, - mantis->mantis_int_stat & MANTIS_INT_I2CDONE, - msecs_to_jiffies(50)) == -ERESTARTSYS) { - - dprintk(MANTIS_DEBUG, 1, "Master !I2CDONE"); - rc = -EREMOTEIO; - } - - while (!(mantis->mantis_int_stat & MANTIS_INT_I2CRACK)) { - dprintk(MANTIS_DEBUG, 1, "Waiting for Slave RACK"); - mantis->mantis_int_stat = mmread(MANTIS_INT_STAT); - msleep(5); - timeout++; - if (timeout > 500) { - dprintk(MANTIS_ERROR, 1, "Slave RACK Fail !"); - rc = -EREMOTEIO; - break; - } - } - udelay(350); - - return rc; -} - static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { - u32 rxd, i; + u32 rxd, i, stat, trials; dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); @@ -82,10 +53,15 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(rxd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) != 0) { - dprintk(MANTIS_DEBUG, 1, "ACK failed"); - return -EREMOTEIO; + + /* wait for xfer completion */ + for (trials = 0; trials < 100; trials++) { + udelay(500); + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CDONE) + break; } + rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); @@ -98,7 +74,7 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg) { int i; - u32 txd = 0; + u32 txd = 0, stat, trials; dprintk(MANTIS_INFO, 0, " %s: Address=[0x%02x] [ ", __func__, msg->addr); @@ -115,9 +91,13 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT); mmwrite(txd, MANTIS_I2CDATA_CTL); - if (mantis_ack_wait(mantis) != 0) { - dprintk(MANTIS_DEBUG, 1, "ACK failed"); - return -EREMOTEIO; + + /* wait for xfer completion */ + for (trials = 0; trials < 100; trials++) { + udelay(500); + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CDONE) + break; } } dprintk(MANTIS_INFO, 0, "]\n"); @@ -127,20 +107,77 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { - int ret = 0, i; + int ret = 0, i = 0, trials; + u32 stat, data, txd; struct mantis_pci *mantis; + struct mantis_hwconfig *config; mantis = i2c_get_adapdata(adapter); + BUG_ON(!mantis); + config = mantis->hwconfig; + BUG_ON(!config); + + dprintk(MANTIS_DEBUG, 1, "Messages:%d", num); mutex_lock(&mantis->i2c_lock); - for (i = 0; i < num; i++) { - if (msgs[i].flags & I2C_M_RD) - ret = mantis_i2c_read(mantis, &msgs[i]); - else - ret = mantis_i2c_write(mantis, &msgs[i]); - - if (ret < 0) - goto bail_out; + + while (i < num) { + /* Byte MODE */ + if (((i + 1) < num) && + (msgs[i].len < 2) && + (msgs[i + 1].len < 2) && + (msgs[i + 1].flags & I2C_M_RD)) { + + dprintk(MANTIS_DEBUG, 0, " Byte MODE:\n"); + + /* Read operation */ + txd = msgs[i].addr << 25 | (0x1 << 24) + | (msgs[i].buf[0] << 16) + | MANTIS_I2C_RATE_3; + + mmwrite(txd, MANTIS_I2CDATA_CTL); + /* wait for xfer completion */ + for (trials = 0; trials < 100; trials++) { + udelay(500); + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CDONE) + break; + } + + /* check for xfer completion */ + if (stat & MANTIS_INT_I2CDONE) { + /* check xfer was acknowledged */ + if (stat & MANTIS_INT_I2CRACK) { + data = mmread(MANTIS_I2CDATA_CTL); + msgs[i + 1].buf[0] = (data >> 8) & 0xff; + dprintk(MANTIS_DEBUG, 0, " Byte <%d> RXD=0x%02x [%02x]\n", 0x0, data, msgs[i + 1].buf[0]); + } else { + /* I/O error */ + dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__); + ret = -EIO; + break; + } + } else { + /* I/O error */ + dprintk(MANTIS_ERROR, 1, " I/O error, LINE:%d", __LINE__); + ret = -EIO; + break; + } + i += 2; /* Write/Read operation in one go */ + } + + if (i < num) { + if (msgs[i].flags & I2C_M_RD) + ret = mantis_i2c_read(mantis, &msgs[i]); + else + ret = mantis_i2c_write(mantis, &msgs[i]); + + i++; + if (ret < 0) + goto bail_out; + } + } + mutex_unlock(&mantis->i2c_lock); return num; @@ -189,9 +226,9 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) intstat = mmread(MANTIS_INT_STAT); intmask = mmread(MANTIS_INT_MASK); mmwrite(intstat, MANTIS_INT_STAT); - mmwrite(intmask | MANTIS_INT_I2CDONE, MANTIS_INT_MASK); - - dprintk(MANTIS_DEBUG, 1, "Status=<%02x> Mask=<%02x>", intstat, intmask); + dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt"); + intmask = mmread(MANTIS_INT_MASK); + mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK); return 0; } @@ -199,6 +236,12 @@ EXPORT_SYMBOL_GPL(mantis_i2c_init); int __devexit mantis_i2c_exit(struct mantis_pci *mantis) { + u32 intmask; + + dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt"); + intmask = mmread(MANTIS_INT_MASK); + mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK); + dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter"); return i2c_del_adapter(&mantis->adapter); } diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h index 1e49ecfeee3..d40da4fa000 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.h +++ b/drivers/media/dvb/mantis/mantis_i2c.h @@ -1,6 +1,9 @@ #ifndef __MANTIS_I2C_H #define __MANTIS_I2C_H +#define I2C_STOP (1 << 0) +#define I2C_READ (1 << 1) + extern int mantis_i2c_init(struct mantis_pci *mantis); extern int mantis_i2c_exit(struct mantis_pci *mantis); diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index 4700088f038..448e2c3e344 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -36,13 +36,14 @@ #include "mantis_reg.h" #include "mantis_ioc.h" -static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) +static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length) { struct i2c_adapter *adapter = &mantis->adapter; - int err; + u8 buf = reg; + struct i2c_msg msg[] = { - { .addr = 0x50, .flags = 0, .buf = data, .len = 1 }, + { .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 }, { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, }; @@ -56,32 +57,12 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) return 0; } - -static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) -{ - struct i2c_adapter *adapter = &mantis->adapter; - int err; - - struct i2c_msg msg = { .addr = 0x50, .flags = 0, .buf = data, .len = length }; - - err = i2c_transfer(adapter, &msg, 1); - if (err < 0) { - dprintk(MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", - err, length, data[0], data[1]); - - return err; - } - - return 0; -} - int mantis_get_mac(struct mantis_pci *mantis) { int err; + u8 mac_addr[6] = {0}; - mantis->mac_address[0] = 0x08; - - err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); + err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6); if (err < 0) { dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err); @@ -90,9 +71,12 @@ int mantis_get_mac(struct mantis_pci *mantis) dprintk(MANTIS_ERROR, 0, " MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n", - mantis->mac_address[0], mantis->mac_address[1], - mantis->mac_address[2], mantis->mac_address[3], - mantis->mac_address[4], mantis->mac_address[5]); + mac_addr[0], + mac_addr[1], + mac_addr[2], + mac_addr[3], + mac_addr[4], + mac_addr[5]); return 0; } @@ -103,12 +87,14 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { u32 cur; + dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value); cur = mmread(MANTIS_GPIF_ADDR); if (value) mantis->gpio_status = cur | (1 << bitpos); else mantis->gpio_status = cur & (~(1 << bitpos)); + dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status); mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR); mmwrite(0x00, MANTIS_GPIF_DOUT); } diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 4b974eeefa9..9efcfa7b8ab 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -30,46 +30,41 @@ #include "dvb_net.h" #include "zl10353.h" +#include "tda665x.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp3030.h" struct zl10353_config mantis_vp3030_config = { - .demod_address = 0x0f, + .demod_address = 0x0f, +}; + +struct tda665x_config env57h12d5_config = { + .name = "ENV57H12D5 (ET-50DT)", + .addr = 0x60, + .frequency_min = 47000000, + .frequency_max = 862000000, + .frequency_offst = 3616667, + .ref_multiplier = 6, /* 1/6 MHz */ + .ref_divider = 100000, /* 1/6 MHz */ }; #define MANTIS_MODEL_NAME "VP-3030" #define MANTIS_DEV_TYPE "DVB-T" -int panasonic_en57h12d5_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) -{ - u8 buf[4]; - int rc; - struct mantis_pci *mantis = fe->dvb->priv; - - struct i2c_msg tuner_msg = { - .addr = 0x60, - .flags = 0, - .buf = buf, - .len = sizeof (buf) - }; - - if ((params->frequency < 950000) || (params->frequency > 2150000)) - return -EINVAL; - rc = i2c_transfer(&mantis->adapter, &tuner_msg, 1); - if (rc != 1) { - printk("%s: I2C Transfer returned [%d]\n", __func__, rc); - return -EIO; - } - msleep_interruptible(1); - printk("%s: Send params to tuner ok!!!\n", __func__); - - return 0; -} static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) { struct i2c_adapter *adapter = &mantis->adapter; + struct mantis_hwconfig *config = mantis->hwconfig; + int err = 0; + + gpio_set_bits(mantis, config->reset, 0); + msleep(100); + err = mantis_frontend_power(mantis, POWER_ON); + msleep(100); + gpio_set_bits(mantis, config->reset, 1); dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); fe = zl10353_attach(&mantis_vp3030_config, adapter); @@ -77,6 +72,7 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * if (!fe) return -1; + tda665x_attach(fe, &env57h12d5_config, adapter); mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -93,4 +89,6 @@ struct mantis_hwconfig vp3030_config = { .bytes = 0, .frontend_init = vp3030_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; -- cgit v1.2.3 From bc832fa2c0310c25ed60204616ccef4f8db088f3 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 05:57:28 -0300 Subject: V4L/DVB (13798): [Mantis] Enable power for all cards, use byte mode only on relevant devices Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_vp3028.c | 27 ++++++++++++----- drivers/media/dvb/mantis/mantis_common.h | 13 ++++++-- drivers/media/dvb/mantis/mantis_i2c.c | 47 ++++++++++++++++++++++------- drivers/media/dvb/mantis/mantis_vp1033.c | 36 ++++++++++++++++------ drivers/media/dvb/mantis/mantis_vp1034.c | 32 +++++++++++++++----- drivers/media/dvb/mantis/mantis_vp2033.c | 50 +++++++++++++++++++++---------- drivers/media/dvb/mantis/mantis_vp2040.c | 51 +++++++++++++++++++++----------- drivers/media/dvb/mantis/mantis_vp3030.c | 22 ++++++++++---- 8 files changed, 203 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index ba0c7e58b7a..16b39d3b9ac 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -45,17 +45,30 @@ struct zl10353_config hopper_vp3028_config = { static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe) { struct i2c_adapter *adapter = &mantis->adapter; + struct mantis_hwconfig *config = mantis->hwconfig; int err = 0; + gpio_set_bits(mantis, config->reset, 0); + msleep(100); err = mantis_frontend_power(mantis, POWER_ON); - mantis_frontend_soft_reset(mantis); - - dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); - fe = zl10353_attach(&hopper_vp3028_config, adapter); - - if (!fe) - return -1; + msleep(100); + gpio_set_bits(mantis, config->reset, 1); + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + msleep(250); + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&hopper_vp3028_config, adapter); + + if (!fe) + return -1; + } else { + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; + } dprintk(MANTIS_ERROR, 1, "Done!"); return 0; diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index e912c5962e3..6ae3aabe560 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -32,6 +32,7 @@ #define MANTIS_NOTICE 1 #define MANTIS_INFO 2 #define MANTIS_DEBUG 3 +#define MANTIS_TMG 9 #define dprintk(y, z, format, arg...) do { \ if (z) { \ @@ -43,6 +44,8 @@ printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y)) \ printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ + else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y)) \ + printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg); \ } else { \ if (mantis->verbose > y) \ printk(format , ##arg); \ @@ -54,9 +57,6 @@ #define mmwrite(dat, addr) mwrite((dat), (mantis->mmio + (addr))) #define mmread(addr) mread(mantis->mmio + (addr)) -#define mmand(dat, addr) mmwrite((dat) & mmread(addr), addr) -#define mmor(dat, addr) mmwrite((dat) | mmread(addr), addr) -#define mmaor(dat, addr) mmwrite((dat) | ((mask) & mmread(addr)), addr) #define MANTIS_TS_188 0 #define MANTIS_TS_204 1 @@ -75,6 +75,11 @@ .driver_data = (unsigned long) (__configptr) \ } +enum mantis_i2c_mode { + MANTIS_PAGE_MODE = 0, + MANTIS_BYTE_MODE, +}; + struct mantis_pci; struct mantis_hwconfig { @@ -91,6 +96,8 @@ struct mantis_hwconfig { u8 power; u8 reset; + + enum mantis_i2c_mode i2c_mode; }; struct mantis_pci { diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 16b9e7e77b8..758f32a63b2 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -35,6 +35,8 @@ #define I2C_HW_B_MANTIS 0x1c +#define TRIALS 10000 + static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) { u32 rxd, i, stat, trials; @@ -55,13 +57,25 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) mmwrite(rxd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ - for (trials = 0; trials < 100; trials++) { - udelay(500); + for (trials = 0; trials < TRIALS; trials++) { + msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; } + dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials); + + /* wait for xfer completion */ + for (trials = 0; trials < TRIALS; trials++) { + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CRACK) + break; + msleep(1); + } + + dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); + rxd = mmread(MANTIS_I2CDATA_CTL); msg->buf[i] = (u8)((rxd >> 8) & 0xFF); dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]); @@ -93,12 +107,24 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg mmwrite(txd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ - for (trials = 0; trials < 100; trials++) { - udelay(500); + for (trials = 0; trials < TRIALS; trials++) { + msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; } + + dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials); + + /* wait for xfer completion */ + for (trials = 0; trials < TRIALS; trials++) { + stat = mmread(MANTIS_INT_STAT); + if (stat & MANTIS_INT_I2CRACK) + break; + msleep(1); + } + + dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); } dprintk(MANTIS_INFO, 0, "]\n"); @@ -122,10 +148,11 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in while (i < num) { /* Byte MODE */ - if (((i + 1) < num) && - (msgs[i].len < 2) && - (msgs[i + 1].len < 2) && - (msgs[i + 1].flags & I2C_M_RD)) { + if ((config->i2c_mode & MANTIS_BYTE_MODE) && + ((i + 1) < num) && + (msgs[i].len < 2) && + (msgs[i + 1].len < 2) && + (msgs[i + 1].flags & I2C_M_RD)) { dprintk(MANTIS_DEBUG, 0, " Byte MODE:\n"); @@ -136,8 +163,8 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in mmwrite(txd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ - for (trials = 0; trials < 100; trials++) { - udelay(500); + for (trials = 0; trials < TRIALS; trials++) { + msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index f2092ce9c4b..0bea6e89f55 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -31,7 +31,10 @@ #include "stv0299.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp1033.h" +#include "mantis_reg.h" u8 lgtdqcs001f_inittab[] = { 0x01, 0x15, @@ -163,19 +166,32 @@ static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); - fe = stv0299_attach(&lgtdqcs001f_config, adapter); + int err = 0; - if (fe) { - fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; - dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", - lgtdqcs001f_config.demod_address); + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); - dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); + dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)"); + fe = stv0299_attach(&lgtdqcs001f_config, adapter); + + if (fe) { + fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set; + dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x", + lgtdqcs001f_config.demod_address); + + dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success"); + } else { + return -1; + } } else { - return -1; - } + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + return -EIO; + } mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -192,4 +208,6 @@ struct mantis_hwconfig vp1033_config = { .bytes = 0, .frontend_init = vp1033_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 40778ec8f46..98a4ec89f04 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -32,6 +32,7 @@ #include "mb86a16.h" #include "mantis_common.h" #include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp1034.h" #include "mantis_reg.h" @@ -74,17 +75,30 @@ static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); - fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); - if (fe) { - dprintk(MANTIS_ERROR, 1, - "found MB86A16 DVB-S/DSS frontend @0x%02x", - vp1034_mb86a16_config.demod_address); + int err = 0; + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + + dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); + fe = mb86a16_attach(&vp1034_mb86a16_config, adapter); + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found MB86A16 DVB-S/DSS frontend @0x%02x", + vp1034_mb86a16_config.demod_address); + + } else { + return -1; + } } else { - return -1; - } + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + return -EIO; + } mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -101,4 +115,6 @@ struct mantis_hwconfig vp1034_config = { .bytes = 0, .frontend_init = vp1034_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 877329175d0..cef108c5ffc 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -31,6 +31,8 @@ #include "tda1002x.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp2033.h" #define MANTIS_MODEL_NAME "VP-2033" @@ -123,32 +125,46 @@ static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, - adapter, - read_pwm(mantis)); + int err = 0; - if (fe) { - dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", - vp2033_tda1002x_cu1216_config.demod_address); - } else { - fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2033_tda1002x_cu1216_config, adapter, read_pwm(mantis)); if (fe) { dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", vp2033_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2033_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2033_tda1002x_cu1216_config.demod_address); + } } - } - if (fe) { - fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; - dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } } else { - return -1; + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; } mantis->fe = fe; @@ -167,4 +183,6 @@ struct mantis_hwconfig vp2033_config = { .bytes = 0, .frontend_init = vp2033_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index 51b082f7f91..e2019884ac3 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -31,6 +31,8 @@ #include "tda1002x.h" #include "mantis_common.h" +#include "mantis_ioc.h" +#include "mantis_dvb.h" #include "mantis_vp2040.h" #define MANTIS_MODEL_NAME "VP-2040" @@ -123,34 +125,47 @@ static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * { struct i2c_adapter *adapter = &mantis->adapter; - dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); - fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, - adapter, - read_pwm(mantis)); + int err = 0; - if (fe) { - dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", - vp2040_tda1002x_cu1216_config.demod_address); - } else { - fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + err = mantis_frontend_power(mantis, POWER_ON); + if (err == 0) { + mantis_frontend_soft_reset(mantis); + msleep(250); + + dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)"); + fe = tda10021_attach(&vp2040_tda1002x_cu1216_config, adapter, read_pwm(mantis)); if (fe) { dprintk(MANTIS_ERROR, 1, - "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + "found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x", vp2040_tda1002x_cu1216_config.demod_address); + } else { + fe = tda10023_attach(&vp2040_tda10023_cu1216_config, + adapter, + read_pwm(mantis)); + + if (fe) { + dprintk(MANTIS_ERROR, 1, + "found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x", + vp2040_tda1002x_cu1216_config.demod_address); + } } - } - if (fe) { - fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; - dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + if (fe) { + fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set; + dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success"); + } else { + return -1; + } } else { - return -1; - } + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + return -EIO; + } mantis->fe = fe; dprintk(MANTIS_DEBUG, 1, "Done!"); @@ -167,4 +182,6 @@ struct mantis_hwconfig vp2040_config = { .bytes = 0, .frontend_init = vp2040_frontend_init, + .power = GPIF_A12, + .reset = GPIF_A13, }; diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 9efcfa7b8ab..a44fac3aabc 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -66,13 +66,23 @@ static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * msleep(100); gpio_set_bits(mantis, config->reset, 1); - dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); - fe = zl10353_attach(&mantis_vp3030_config, adapter); + if (err == 0) { + msleep(250); + dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)"); + fe = zl10353_attach(&mantis_vp3030_config, adapter); - if (!fe) - return -1; + if (!fe) + return -1; - tda665x_attach(fe, &env57h12d5_config, adapter); + tda665x_attach(fe, &env57h12d5_config, adapter); + } else { + dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>", + adapter->name, + err); + + return -EIO; + + } mantis->fe = fe; dprintk(MANTIS_ERROR, 1, "Done!"); @@ -91,4 +101,6 @@ struct mantis_hwconfig vp3030_config = { .frontend_init = vp3030_frontend_init, .power = GPIF_A12, .reset = GPIF_A13, + + .i2c_mode = MANTIS_BYTE_MODE }; -- cgit v1.2.3 From 68fe255cd15cf1fe04877fbbb0eafe80c43eff5d Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 09:01:35 -0300 Subject: V4L/DVB (13799): [Mantis] Unregister frontend Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 42f658b06a6..9d9c5582ada 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -252,7 +252,8 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) err5: tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); - + dvb_unregister_frontend(mantis->fe); + dvb_frontend_detach(mantis->fe); err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); @@ -281,7 +282,7 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) err = mantis_frontend_shutdown(mantis); if (err != 0) dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); - + dvb_frontend_detach(mantis->fe); dvb_unregister_frontend(mantis->fe); } -- cgit v1.2.3 From 281859179f731b28aae78d13b2e8720219492000 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 4 Dec 2009 09:02:00 -0300 Subject: V4L/DVB (13800): [Mantis] I2C optimization. Required delay is much lesser than 1mS. Do not wait, keep looping instead. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 758f32a63b2..9d2b51d2e4b 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -58,7 +58,6 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) /* wait for xfer completion */ for (trials = 0; trials < TRIALS; trials++) { - msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; @@ -71,7 +70,6 @@ static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CRACK) break; - msleep(1); } dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); @@ -108,7 +106,6 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg /* wait for xfer completion */ for (trials = 0; trials < TRIALS; trials++) { - msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; @@ -121,7 +118,6 @@ static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CRACK) break; - msleep(1); } dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials); @@ -164,7 +160,6 @@ static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, in mmwrite(txd, MANTIS_I2CDATA_CTL); /* wait for xfer completion */ for (trials = 0; trials < TRIALS; trials++) { - msleep(1); stat = mmread(MANTIS_INT_STAT); if (stat & MANTIS_INT_I2CDONE) break; -- cgit v1.2.3 From 5dd83a35bea908ebb8243d67d8c251eed2bb5cc8 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 06:15:27 -0300 Subject: V4L/DVB (13801): [MB86A16] Use the search callback Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 45 ++++++++++++++++------------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index eddb35baaf0..33387b78d85 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1487,16 +1487,19 @@ static int mb86a16_set_fe(struct mb86a16_state *state) } else { dprintk(verbose, MB86A16_INFO, 1, "NO -- SYNC"); SEQ_set(state, 1); + ret = -1; } } } else { dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + ret = -1; } sync = sync_chk(state, &junk); if (sync) { dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******"); freqerr_chk(state, state->frequency, state->srate, 1); + ret = 0; break; } } @@ -1610,33 +1613,21 @@ err: return -EREMOTEIO; } -#define MB86A16_FE_ALGO 1 - -static int mb86a16_frontend_algo(struct dvb_frontend *fe) -{ - return MB86A16_FE_ALGO; -} - -static int mb86a16_set_frontend(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p, - unsigned int mode_flags, - int *delay, - fe_status_t *status) +static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) { - int ret = 0; struct mb86a16_state *state = fe->demodulator_priv; - if (p != NULL) { - state->frequency = p->frequency / 1000; - state->srate = p->u.qpsk.symbol_rate / 1000; - ret = mb86a16_set_fe(state); - } - if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) - mb86a16_read_status(fe, status); + state->frequency = p->frequency / 1000; + state->srate = p->u.qpsk.symbol_rate / 1000; - *delay = HZ/3000; + if (!mb86a16_set_fe(state)) { + dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK"); + return DVBFE_ALGO_SEARCH_SUCCESS; + } - return ret; + dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!"); + return DVBFE_ALGO_SEARCH_FAILED; } static void mb86a16_release(struct dvb_frontend *fe) @@ -1809,6 +1800,11 @@ static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } +static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe) +{ + return DVBFE_ALGO_CUSTOM; +} + static struct dvb_frontend_ops mb86a16_ops = { .info = { .name = "Fujitsu MB86A16 DVB-S", @@ -1826,9 +1822,10 @@ static struct dvb_frontend_ops mb86a16_ops = { FE_CAN_FEC_AUTO }, .release = mb86a16_release, - .tune = mb86a16_set_frontend, - .read_status = mb86a16_read_status, + .get_frontend_algo = mb86a16_frontend_algo, + .search = mb86a16_search, + .read_status = mb86a16_read_status, .init = mb86a16_init, .sleep = mb86a16_sleep, .read_status = mb86a16_read_status, -- cgit v1.2.3 From 0bdc799b8b82cf61c86604291c53998febc96403 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 06:17:54 -0300 Subject: V4L/DVB (13802): [Mantis/Hopper] Fix all build related warnings Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_cards.c | 4 ---- drivers/media/dvb/mantis/hopper_vp3028.c | 1 - drivers/media/dvb/mantis/mantis_ca.c | 1 - drivers/media/dvb/mantis/mantis_cards.c | 13 ------------- drivers/media/dvb/mantis/mantis_dvb.c | 1 - drivers/media/dvb/mantis/mantis_evm.c | 1 - drivers/media/dvb/mantis/mantis_hif.c | 17 ----------------- drivers/media/dvb/mantis/mantis_ioc.c | 1 - drivers/media/dvb/mantis/mantis_pcmcia.c | 1 - drivers/media/dvb/mantis/mantis_uart.c | 7 +++---- drivers/media/dvb/mantis/mantis_vp1033.c | 1 - drivers/media/dvb/mantis/mantis_vp1034.c | 1 - drivers/media/dvb/mantis/mantis_vp1041.c | 1 - drivers/media/dvb/mantis/mantis_vp2033.c | 1 - drivers/media/dvb/mantis/mantis_vp2040.c | 1 - drivers/media/dvb/mantis/mantis_vp3030.c | 1 - 16 files changed, 3 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 01a9ff07d77..6d5d101f0ab 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -190,10 +190,6 @@ static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_dev return err; -fail5: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); - mantis_dvb_exit(mantis); - fail4: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); mantis_dma_exit(mantis); diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index 16b39d3b9ac..76cad876338 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 4151cba35e7..88899ac96d6 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index 638177ce72a..0b52f996f8e 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -197,19 +197,6 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev devs++; return err; - -fail7: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); - mantis_uart_exit(mantis); - -fail6: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis CA exit! <%d>", err); - mantis_ca_exit(mantis); - -fail5: - dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB exit! <%d>", err); - mantis_dvb_exit(mantis); - fail4: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); mantis_dma_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 9d9c5582ada..1e08e310763 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -20,7 +20,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 2005b2489b7..9304b0edd89 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -20,7 +20,6 @@ #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index bb05427fdeb..73e5ca0c6c1 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include @@ -40,22 +39,6 @@ #include "mantis_reg.h" -static int mantis_hif_data_available(struct mantis_ca *ca) -{ - struct mantis_pci *mantis = ca->ca_priv; - int rc = 0; - - if (wait_event_interruptible_timeout(ca->hif_data_wq, - ca->sbuf_status & MANTIS_SBUF_DATA_AVAIL, - msecs_to_jiffies(500)) == -ERESTARTSYS) { - - dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Read wait event timeout !", mantis->num); - rc = -EREMOTEIO; - } - ca->sbuf_status &= ~MANTIS_SBUF_DATA_AVAIL; - udelay(2); - return rc; -} static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca) { diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index 448e2c3e344..dd6636999ad 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -21,7 +21,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index 90ca356985e..d6bca3e5859 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -20,7 +20,6 @@ #include -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index fb423b0a58f..03b47cf15f8 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -26,19 +26,18 @@ struct mantis_uart_params { int mantis_uart_read(struct mantis_pci *mantis, u8 *data) { struct mantis_hwconfig *config = mantis->hwconfig; - u32 stat, i; - unsigned long flags; + u32 stat = 0, i; /* get data */ for (i = 0; i < (config->bytes + 1); i++) { + stat = mmread(MANTIS_UART_STAT); + if (stat & MANTIS_UART_RXFIFO_FULL) { dprintk(MANTIS_ERROR, 1, "RX Fifo FULL"); } data[i] = mmread(MANTIS_UART_RXD) & 0x3f; - stat = mmread(MANTIS_UART_STAT); - dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f); if (data[i] & (1 << 7)) { diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 0bea6e89f55..c9760b00d0a 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 98a4ec89f04..7ddd149b0fe 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 1181fad3b27..368fc815a61 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index cef108c5ffc..45f71749bb9 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index e2019884ac3..8471bff672f 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index a44fac3aabc..1895e956b16 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include -- cgit v1.2.3 From 83dbe82bd7766e5045e6561bd44e22b801e7ad76 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 9 Dec 2009 19:00:33 -0300 Subject: V4L/DVB (13803): Remove unused dependency on CU1216 Thanks to Matthias Wachter for pointing it out. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index aaf025097b4..f9219cd7bb0 100644 --- a/drivers/media/dvb/mantis/Kconfig +++ b/drivers/media/dvb/mantis/Kconfig @@ -11,7 +11,6 @@ config DVB_MANTIS tristate "MANTIS based cards" depends on MANTIS_CORE && DVB_CORE && PCI && I2C select DVB_MB86A16 - select DVB_CU1216 select DVB_ZL10353 select DVB_STV0299 select DVB_PLL -- cgit v1.2.3 From 0ac6e141eb105f5845eb7066b5279709393b1c78 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 9 Dec 2009 19:27:17 -0300 Subject: V4L/DVB (13804): Remove unused I2C Adapter ID Signed-off-by: Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 9d2b51d2e4b..7bb4e78aa71 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -33,8 +33,6 @@ #include "mantis_reg.h" #include "mantis_i2c.h" -#define I2C_HW_B_MANTIS 0x1c - #define TRIALS 10000 static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg) @@ -234,7 +232,6 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) i2c_adapter->class = I2C_CLASS_TV_DIGITAL; i2c_adapter->algo = &mantis_algo; i2c_adapter->algo_data = NULL; - i2c_adapter->id = I2C_HW_B_MANTIS; i2c_adapter->timeout = 500; i2c_adapter->retries = 3; i2c_adapter->dev.parent = &pdev->dev; -- cgit v1.2.3 From c5e598a6f89ca7335db9f327e24e3abd13d137cf Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Wed, 9 Dec 2009 19:59:26 -0300 Subject: V4L/DVB (13805): Fix: Unregister the frontend before detaching Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_dvb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 1e08e310763..54bf4ea9efd 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -281,8 +281,8 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) err = mantis_frontend_shutdown(mantis); if (err != 0) dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); - dvb_frontend_detach(mantis->fe); dvb_unregister_frontend(mantis->fe); + dvb_frontend_detach(mantis->fe); } tasklet_kill(&mantis->tasklet); -- cgit v1.2.3 From a1497357dce240880d984f4b657b54245f739dbc Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Fri, 11 Dec 2009 20:41:07 -0300 Subject: V4L/DVB (13806): Register and Initialize Remote control Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Makefile | 3 +- drivers/media/dvb/mantis/mantis_cards.c | 14 +++ drivers/media/dvb/mantis/mantis_common.h | 2 + drivers/media/dvb/mantis/mantis_input.c | 147 +++++++++++++++++++++++++++++++ drivers/media/dvb/mantis/mantis_uart.c | 55 +++++++++--- drivers/media/dvb/mantis/mantis_uart.h | 3 +- 6 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 drivers/media/dvb/mantis/mantis_input.c (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile index 399c9018cdb..98dc5cd258a 100644 --- a/drivers/media/dvb/mantis/Makefile +++ b/drivers/media/dvb/mantis/Makefile @@ -7,7 +7,8 @@ mantis_core-objs := mantis_ioc.o \ mantis_evm.o \ mantis_hif.o \ mantis_ca.o \ - mantis_pcmcia.o + mantis_pcmcia.o \ + mantis_input.o mantis-objs := mantis_cards.o \ mantis_vp1033.o \ diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index 0b52f996f8e..f3fefbbc876 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -194,9 +194,21 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err); goto fail4; } + err = mantis_uart_init(mantis); + if (err < 0) { + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err); + goto fail6; + } + devs++; return err; + + + dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err); + mantis_uart_exit(mantis); + +fail6: fail4: dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err); mantis_dma_exit(mantis); @@ -222,6 +234,8 @@ static void __devexit mantis_pci_remove(struct pci_dev *pdev) struct mantis_pci *mantis = pci_get_drvdata(pdev); if (mantis) { + + mantis_uart_exit(mantis); mantis_dvb_exit(mantis); mantis_dma_exit(mantis); mantis_i2c_exit(mantis); diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index 6ae3aabe560..c2d085460e6 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -170,6 +170,8 @@ struct mantis_pci { wait_queue_head_t uart_wq; struct work_struct uart_work; spinlock_t uart_lock; + + struct input_dev *rc; }; #define MANTIS_HIF_STATUS (mantis->gpio_status) diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c new file mode 100644 index 00000000000..9395fcf4a45 --- /dev/null +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -0,0 +1,147 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "dmxdev.h" +#include "dvbdev.h" +#include "dvb_demux.h" +#include "dvb_frontend.h" +#include "dvb_net.h" + +#include "mantis_common.h" +#include "mantis_reg.h" +#include "mantis_uart.h" + +static struct ir_scancode mantis_ir_table[] = { + { 0x29, KEY_POWER }, + { 0x28, KEY_FAVORITES }, + { 0x30, KEY_TEXT }, + { 0x17, KEY_INFO }, // Preview + { 0x23, KEY_EPG }, + { 0x3b, KEY_F22 },// Record List + { 0x3c, KEY_1 }, + { 0x3e, KEY_2 }, + { 0x39, KEY_3 }, + { 0x36, KEY_4 }, + { 0x22, KEY_5 }, + { 0x20, KEY_6 }, + { 0x32, KEY_7 }, + { 0x26, KEY_8 }, + { 0x24, KEY_9 }, + { 0x2a, KEY_0 }, + + { 0x33, KEY_CANCEL }, + { 0x2c, KEY_BACK }, + { 0x15, KEY_CLEAR }, + { 0x3f, KEY_TAB }, + { 0x10, KEY_ENTER }, + { 0x14, KEY_UP }, + { 0x0d, KEY_RIGHT }, + { 0x0e, KEY_DOWN }, + { 0x11, KEY_LEFT }, + + { 0x21, KEY_VOLUMEUP }, + { 0x35, KEY_VOLUMEDOWN }, + { 0x3d, KEY_CHANNELDOWN }, + { 0x3a, KEY_CHANNELUP }, + { 0x2e, KEY_RECORD }, + { 0x2b, KEY_PLAY }, + { 0x13, KEY_PAUSE }, + { 0x25, KEY_STOP }, + + { 0x1f, KEY_REWIND }, + { 0x2d, KEY_FASTFORWARD }, + { 0x1e, KEY_PREVIOUS }, // Replay |< + { 0x1d, KEY_NEXT }, // Skip >| + + { 0x0b, KEY_CAMERA }, // Capture + { 0x0f, KEY_LANGUAGE }, // SAP + { 0x18, KEY_MODE }, // PIP + { 0x12, KEY_ZOOM }, // Full screen, + { 0x1c, KEY_SUBTITLE }, + { 0x2f, KEY_MUTE }, + { 0x16, KEY_F20 }, // L/R, + { 0x38, KEY_F21 }, // Hibernate, + + { 0x37, KEY_SWITCHVIDEOMODE }, // A/V + { 0x31, KEY_AGAIN }, // Recall, + { 0x1a, KEY_KPPLUS }, // Zoom+, + { 0x19, KEY_KPMINUS }, // Zoom-, + { 0x27, KEY_RED }, + { 0x0C, KEY_GREEN }, + { 0x01, KEY_YELLOW }, + { 0x00, KEY_BLUE }, +}; + +struct ir_scancode_table ir_mantis = { + .scan = mantis_ir_table, + .size = ARRAY_SIZE(mantis_ir_table), +}; +EXPORT_SYMBOL_GPL(ir_mantis); + +int mantis_input_init(struct mantis_pci *mantis) +{ + struct input_dev *rc; + struct ir_input_state rc_state; + char name[80], dev[80]; + int err; + + rc = input_allocate_device(); + if (!rc) { + dprintk(MANTIS_ERROR, 1, "Input device allocate failed"); + return -ENOMEM; + } + + sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name); + sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev)); + + rc->name = name; + rc->phys = dev; + + ir_input_init(rc, &rc_state, IR_TYPE_OTHER, &ir_mantis); + + rc->id.bustype = BUS_PCI; + rc->id.vendor = mantis->vendor_id; + rc->id.product = mantis->device_id; + rc->id.version = 1; + rc->dev = mantis->pdev->dev; + + err = input_register_device(rc); + if (err) { + dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); + return -ENODEV; + } + + mantis->rc = rc; + + return 0; +} + +int mantis_exit(struct mantis_pci *mantis) +{ + struct input_dev *rc = mantis->rc; + + input_unregister_device(rc); + + return 0; +} diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c index 03b47cf15f8..7d2f2398fa8 100644 --- a/drivers/media/dvb/mantis/mantis_uart.c +++ b/drivers/media/dvb/mantis/mantis_uart.c @@ -1,7 +1,26 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include -#include #include #include #include @@ -21,6 +40,24 @@ struct mantis_uart_params { enum mantis_parity parity; }; +static struct { + char string[7]; +} rates[5] = { + { "9600" }, + { "19200" }, + { "38400" }, + { "57600" }, + { "115200" } +}; + +static struct { + char string[5]; +} parity[3] = { + { "NONE" }, + { "ODD" }, + { "EVEN" } +}; + #define UART_MAX_BUF 16 int mantis_uart_read(struct mantis_pci *mantis, u8 *data) @@ -60,12 +97,10 @@ static void mantis_uart_work(struct work_struct *work) u8 buf[16]; int i; - dprintk(MANTIS_DEBUG, 1, "UART read"); mantis_uart_read(mantis, buf); - dprintk(MANTIS_DEBUG, 1, "UART: "); for (i = 0; i < (config->bytes + 1); i++) - dprintk(MANTIS_DEBUG, 0, "<%02x> ", buf[i]); + dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]); dprintk(MANTIS_DEBUG, 0, "\n"); } @@ -73,15 +108,8 @@ static void mantis_uart_work(struct work_struct *work) static int mantis_uart_setup(struct mantis_pci *mantis, struct mantis_uart_params *params) { - char* rates[] = { "B_9600", "B_19200", "B_38400", "B_57600", "B_115200" }; - char* parity[] = { "NONE", "ODD", "EVEN" }; - u32 reg; - dprintk(MANTIS_DEBUG, 1, "Set Parity <%s> Baud Rate <%s>", - parity[params->parity], - rates[params->baud_rate]); - mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL); reg = mmread(MANTIS_UART_BAUD); @@ -116,10 +144,12 @@ int mantis_uart_init(struct mantis_pci *mantis) struct mantis_hwconfig *config = mantis->hwconfig; struct mantis_uart_params params; - dprintk(MANTIS_DEBUG, 1, "Initializing UART .."); /* default parity: */ params.baud_rate = config->baud_rate; params.parity = config->parity; + dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s", + rates[params.baud_rate].string, + parity[params.parity].string); init_waitqueue_head(&mantis->uart_wq); spin_lock_init(&mantis->uart_lock); @@ -142,6 +172,7 @@ int mantis_uart_init(struct mantis_pci *mantis) mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL); schedule_work(&mantis->uart_work); + dprintk(MANTIS_DEBUG, 1, "UART succesfully initialized"); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 0a42cd01ab2..62ab66ebb97 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -45,10 +45,9 @@ enum mantis_baud { }; enum mantis_parity { - MANTIS_PARITY_UNDEFINED = 0, + MANTIS_PARITY_NONE = 0, MANTIS_PARITY_EVEN, MANTIS_PARITY_ODD, - MANTIS_PARITY_NONE }; struct mantis_pci; -- cgit v1.2.3 From 1e42dc78900e9d0ce89d77f3ba6aca00abd5f1b5 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 12 Dec 2009 03:14:25 -0300 Subject: V4L/DVB (13807): Fix: Free device in the device registration failure case Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 9395fcf4a45..b27d7759788 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -129,6 +129,7 @@ int mantis_input_init(struct mantis_pci *mantis) err = input_register_device(rc); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); + input_free_device(rc); return -ENODEV; } -- cgit v1.2.3 From f5ae4f6f482191c531ea9e50ac91d9bd2ffca171 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 08:47:21 -0300 Subject: V4L/DVB (13809): Fix Checkpatch violations Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 109 +++++++++++++++-------------- drivers/media/dvb/frontends/mb86a16.h | 2 +- drivers/media/dvb/frontends/mb86a16_priv.h | 2 +- drivers/media/dvb/frontends/tda665x.c | 32 ++++----- drivers/media/dvb/frontends/tda665x.h | 2 +- drivers/media/dvb/mantis/hopper_cards.c | 2 +- drivers/media/dvb/mantis/mantis_ca.c | 4 +- drivers/media/dvb/mantis/mantis_cards.c | 2 +- drivers/media/dvb/mantis/mantis_core.c | 48 ++++++++----- drivers/media/dvb/mantis/mantis_core.h | 14 ++-- drivers/media/dvb/mantis/mantis_dma.c | 11 +-- drivers/media/dvb/mantis/mantis_dvb.c | 12 +--- drivers/media/dvb/mantis/mantis_i2c.c | 2 +- drivers/media/dvb/mantis/mantis_input.c | 28 ++++---- drivers/media/dvb/mantis/mantis_reg.h | 2 +- drivers/media/dvb/mantis/mantis_vp1033.c | 12 ++-- drivers/media/dvb/mantis/mantis_vp1034.c | 2 +- drivers/media/dvb/mantis/mantis_vp1041.c | 9 ++- drivers/media/dvb/mantis/mantis_vp2033.c | 2 +- drivers/media/dvb/mantis/mantis_vp2040.c | 2 +- 20 files changed, 155 insertions(+), 144 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 33387b78d85..32f20c68144 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -37,11 +37,11 @@ struct mb86a16_state { const struct mb86a16_config *config; struct dvb_frontend frontend; - // tuning parameters + /* tuning parameters */ int frequency; int srate; - // Internal stuff + /* Internal stuff */ int master_clk; int deci; int csel; @@ -105,7 +105,7 @@ static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val) .flags = 0, .buf = b0, .len = 1 - },{ + }, { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, @@ -435,7 +435,7 @@ static int signal_det(struct mb86a16_state *state, wait_sym = 80000; } for (i = 0; i < 3; i++) { - if (i == 0 ) + if (i == 0) smrtd = smrt * 98 / 100; else if (i == 1) smrtd = smrt; @@ -480,11 +480,11 @@ static int rf_val_set(struct mb86a16_state *state, unsigned char rf_val[5]; int ack = -1; - if (smrt > 37750 ) + if (smrt > 37750) C = 1; else if (smrt > 18875) C = 2; - else if (smrt > 5500 ) + else if (smrt > 5500) C = 3; else C = 4; @@ -526,7 +526,7 @@ static int rf_val_set(struct mb86a16_state *state, rf_val[2] = (M & 0x00ff0) >> 4; rf_val[3] = ((M & 0x0000f) << 4) | B; - // Frequency Set + /* Frequency Set */ if (mb86a16_write(state, 0x21, rf_val[0]) < 0) ack = 0; if (mb86a16_write(state, 0x22, rf_val[1]) < 0) @@ -655,8 +655,8 @@ static int freqerr_chk(struct mb86a16_state *state, unsigned char CRM, AFCML, AFCMH; unsigned char temp1, temp2, temp3; int crm, afcm, AFCM; - int crrerr, afcerr; // [kHz] - int frqerr; // [MHz] + int crrerr, afcerr; /* kHz */ + int frqerr; /* MHz */ int afcen, afcexen = 0; int R, M, fOSC, fOSC_OFS; @@ -718,12 +718,12 @@ static int freqerr_chk(struct mb86a16_state *state, fOSC_OFS = fOSC - fTP; - if (unit == 0) { //[MHz] + if (unit == 0) { /* MHz */ if (crrerr + afcerr + fOSC_OFS * 1000 >= 0) frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000; else frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000; - } else { //[kHz] + } else { /* kHz */ frqerr = crrerr + afcerr + fOSC_OFS * 1000; } @@ -760,13 +760,13 @@ static void swp_info_get(struct mb86a16_state *state, crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs; - if (R == 0 ) + if (R == 0) *fOSC = (crnt_swp_freq + 1000) / 2000 * 2; else *fOSC = (crnt_swp_freq + 500) / 1000; if (*fOSC >= crnt_swp_freq) - *afcex_freq = *fOSC *1000 - crnt_swp_freq; + *afcex_freq = *fOSC * 1000 - crnt_swp_freq; else *afcex_freq = crnt_swp_freq - *fOSC * 1000; @@ -782,7 +782,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V int swp_freq ; if ((i % 2 == 1) && (v <= vmax)) { - // positive v (case 1) + /* positive v (case 1) */ if ((v - 1 == vmin) && (*(V + 30 + v) >= 0) && (*(V + 30 + v - 1) >= 0) && @@ -796,7 +796,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v - 1) >= 0) && (*(V + 30 + v) > *(V + 30 + v - 1)) && (*(V + 30 + v) > SIGMIN)) { - // (case 2) + /* (case 2) */ swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); } else if ((*(V + 30 + v) > 0) && @@ -807,7 +807,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v - 2) > *(V + 30 + v - 3)) && ((*(V + 30 + v - 1) > SIGMIN) || (*(V + 30 + v - 2) > SIGMIN))) { - // (case 3) + /* (case 3) */ if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) { swp_freq = fOSC * 1000 + afcex_freq - swp_ofs; *SIG1 = *(V + 30 + v - 1); @@ -823,7 +823,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v - 1) > *(V + 30 + v - 2)) && ((*(V + 30 + v) > SIGMIN) || (*(V + 30 + v - 1) > SIGMIN))) { - // (case 4) + /* (case 4) */ if (*(V + 30 + v) >= *(V + 30 + v - 1)) { swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); @@ -835,7 +835,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V swp_freq = -1 ; } } else if ((i % 2 == 0) && (v >= vmin)) { - // Negative v (case 1) + /* Negative v (case 1) */ if ((*(V + 30 + v) > 0) && (*(V + 30 + v + 1) > 0) && (*(V + 30 + v + 2) > 0) && @@ -850,7 +850,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v + 1) >= 0) && (*(V + 30 + v + 1) > *(V + 30 + v)) && (*(V + 30 + v + 1) > SIGMIN)) { - // (case 2) + /* (case 2) */ swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; *SIG1 = *(V + 30 + v); } else if ((v == vmin) && @@ -860,18 +860,18 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v) > *(V + 30 + v + 1)) && (*(V + 30 + v) > *(V + 30 + v + 2)) && (*(V + 30 + v) > SIGMIN)) { - // (case 3) + /* (case 3) */ swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); } else if ((*(V + 30 + v) >= 0) && (*(V + 30 + v + 1) >= 0) && (*(V + 30 + v + 2) >= 0) && - (*(V +30 + v + 3) >= 0) && + (*(V + 30 + v + 3) >= 0) && (*(V + 30 + v + 1) > *(V + 30 + v)) && (*(V + 30 + v + 2) > *(V + 30 + v + 3)) && ((*(V + 30 + v + 1) > SIGMIN) || (*(V + 30 + v + 2) > SIGMIN))) { - // (case 4) + /* (case 4) */ if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; *SIG1 = *(V + 30 + v + 1); @@ -889,7 +889,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v + 1) > *(V + 30 + v + 3)) && ((*(V + 30 + v) > SIGMIN) || (*(V + 30 + v + 1) > SIGMIN))) { - // (case 5) + /* (case 5) */ if (*(V + 30 + v) >= *(V + 30 + v + 1)) { swp_freq = fOSC * 1000 + afcex_freq; *SIG1 = *(V + 30 + v); @@ -905,7 +905,7 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V (*(V + 30 + v + 2) > *(V + 30 + v)) && ((*(V + 30 + v + 1) > SIGMIN) || (*(V + 30 + v + 2) > SIGMIN))) { - // (case 6) + /* (case 6) */ if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) { swp_freq = fOSC * 1000 + afcex_freq + swp_ofs; *SIG1 = *(V + 30 + v + 1); @@ -916,8 +916,10 @@ static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V } else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) { swp_freq = fOSC * 1000; *SIG1 = *(V + 30 + v); - } else swp_freq = -1; - } else swp_freq = -1; + } else + swp_freq = -1; + } else + swp_freq = -1; return swp_freq; } @@ -962,7 +964,7 @@ static void afcex_info_get(struct mb86a16_state *state, static int SEQ_set(struct mb86a16_state *state, unsigned char loop) { - // SLOCK0 = 0 + /* SLOCK0 = 0 */ if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); return -EREMOTEIO; @@ -973,7 +975,7 @@ static int SEQ_set(struct mb86a16_state *state, unsigned char loop) static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV) { - // Viterbi Rate, IQ Settings + /* Viterbi Rate, IQ Settings */ if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error"); return -EREMOTEIO; @@ -1031,7 +1033,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) unsigned char TIMINT1, TIMINT2, TIMEXT; unsigned char S0T, S1T; unsigned char S2T; -// unsigned char S2T, S3T; +/* unsigned char S2T, S3T; */ unsigned char S4T, S5T; unsigned char AFCEX_L, AFCEX_H; unsigned char R; @@ -1052,7 +1054,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) int temp_freq, delta_freq; int dagcm[4]; int smrt_d; -// int freq_err; +/* int freq_err; */ int n; int ret = -1; int sync; @@ -1093,19 +1095,19 @@ static int mb86a16_set_fe(struct mb86a16_state *state) } if (EN_set(state, CREN, AFCEN) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "EN set error"); - return -1; // (0, 0) + return -1; /* (0, 0) */ } if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error"); - return -1; // (1, smrt) = (1, symbolrate) + return -1; /* (1, smrt) = (1, symbolrate) */ } if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error"); - return -1; // (0, 1, 2) + return -1; /* (0, 1, 2) */ } if (S01T_set(state, S1T, S0T) < 0) { dprintk(verbose, MB86A16_ERROR, 1, "S01T set error"); - return -1; // (0, 0) + return -1; /* (0, 0) */ } smrt_info_get(state, state->srate); if (smrt_set(state, state->srate) < 0) { @@ -1133,13 +1135,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state) ftemp = ftemp + swp_ofs; vmax++; - // Upper bound + /* Upper bound */ if (ftemp > 2150000) { loop = 0; vmax--; + } else { + if ((ftemp == 2150000) || + (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) + loop = 0; } - else if ((ftemp == 2150000) || (ftemp - state->frequency * 1000 >= fcp + state->srate / 4)) - loop = 0; } loop = 1; @@ -1149,13 +1153,15 @@ static int mb86a16_set_fe(struct mb86a16_state *state) ftemp = ftemp - swp_ofs; vmin--; - // Lower bound + /* Lower bound */ if (ftemp < 950000) { loop = 0; vmin++; + } else { + if ((ftemp == 950000) || + (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) + loop = 0; } - else if ((ftemp == 950000) || (state->frequency * 1000 - ftemp >= fcp + state->srate / 4)) - loop = 0; } wait_t = (8000 + state->srate / 2) / state->srate; @@ -1199,7 +1205,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) V[30 + v] = SIG1 ; swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin, SIG1MIN, fOSC, afcex_freq, - swp_ofs, &SIG1); //changed + swp_ofs, &SIG1); /* changed */ signal_dupl = 0; for (j = 0; j < prev_freq_num; j++) { @@ -1291,7 +1297,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) dprintk(verbose, MB86A16_ERROR, 1, "srst error"); return -1; } - // delay 4~200 + /* delay 4~200 */ wait_t = 200000 / state->master_clk + 200000 / state->srate; msleep(wait_t); afcerr = afcerr_chk(state); @@ -1452,7 +1458,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2; wait_t = 7 + (2097152 + state->srate / 2) / state->srate; } - wait_t *= 2; /* FOS */ + wait_t *= 2; /* FOS */ S2T_set(state, S2T); S45T_set(state, S4T, S5T); Vi_set(state, ETH, VIA); @@ -1461,13 +1467,14 @@ static int mb86a16_set_fe(struct mb86a16_state *state) sync = sync_chk(state, &VIRM); dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync); if (VIRM) { - if (VIRM == 4) { // 5/6 + if (VIRM == 4) { + /* 5/6 */ if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; + wait_t = (786432 + state->srate / 2) / state->srate; else wait_t = (1572864 + state->srate / 2) / state->srate; if (state->srate < 5000) - // FIXME ! , should be a long wait ! + /* FIXME ! , should be a long wait ! */ msleep_interruptible(wait_t); else msleep_interruptible(wait_t); @@ -1477,9 +1484,9 @@ static int mb86a16_set_fe(struct mb86a16_state *state) FEC_srst(state); } } - // 1/2, 2/3, 3/4, 7/8 + /* 1/2, 2/3, 3/4, 7/8 */ if (SIG1 > 110) - wait_t = ( 786432 + state->srate / 2) / state->srate; + wait_t = (786432 + state->srate / 2) / state->srate; else wait_t = (1572864 + state->srate / 2) / state->srate; msleep_interruptible(wait_t); @@ -1491,7 +1498,7 @@ static int mb86a16_set_fe(struct mb86a16_state *state) } } } else { - dprintk (verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); + dprintk(verbose, MB86A16_INFO, 1, "NO -- SIGNAL"); ret = -1; } @@ -1846,7 +1853,7 @@ struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, u8 dev_id = 0; struct mb86a16_state *state = NULL; - state = kmalloc(sizeof (struct mb86a16_state), GFP_KERNEL); + state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL); if (state == NULL) goto error; @@ -1857,7 +1864,7 @@ struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, if (dev_id != 0xfe) goto error; - memcpy(&state->frontend.ops, &mb86a16_ops, sizeof (struct dvb_frontend_ops)); + memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; state->frontend.ops.set_voltage = state->config->set_voltage; diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h index b7545d0343f..68f25a64017 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -35,4 +35,4 @@ extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, struct i2c_adapter *i2c_adap); -#endif //__MB86A16_H +#endif /* __MB86A16_H */ diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h index 5de57006806..d8757fafcf1 100644 --- a/drivers/media/dvb/frontends/mb86a16_priv.h +++ b/drivers/media/dvb/frontends/mb86a16_priv.h @@ -148,4 +148,4 @@ #define MB86A16_DISTMON 0x52 #define MB86A16_VERSION 0x7f -#endif //__MB86A16_PRIV_H +#endif /* __MB86A16_PRIV_H */ diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c index 0732a2d38e1..87d52739c82 100644 --- a/drivers/media/dvb/frontends/tda665x.c +++ b/drivers/media/dvb/frontends/tda665x.c @@ -45,7 +45,7 @@ static int tda665x_read(struct tda665x_state *state, u8 *buf) return err; exit: - printk("%s: I/O Error err=<%d>\n", __func__, err); + printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err); return err; } @@ -61,7 +61,7 @@ static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length) return err; exit: - printk("%s: I/O Error err=<%d>\n", __func__, err); + printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err); return err; } @@ -79,7 +79,7 @@ static int tda665x_get_state(struct dvb_frontend *fe, case DVBFE_TUNER_BANDWIDTH: break; default: - printk("%s: Unknown parameter (param=%d)\n", __func__, param); + printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); err = -EINVAL; break; } @@ -100,13 +100,13 @@ static int tda665x_get_status(struct dvb_frontend *fe, u32 *status) goto exit; if ((result >> 6) & 0x01) { - printk("%s: Tuner Phase Locked\n", __func__); + printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__); *status = 1; } return err; exit: - printk("%s: I/O Error\n", __func__); + printk(KERN_ERR "%s: I/O Error\n", __func__); return err; } @@ -124,7 +124,7 @@ static int tda665x_set_state(struct dvb_frontend *fe, frequency = tstate->frequency; if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) { - printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); + printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency); return -EINVAL; } @@ -133,8 +133,8 @@ static int tda665x_set_state(struct dvb_frontend *fe, frequency += config->ref_divider >> 1; frequency /= config->ref_divider; - buf[0] = (u8 ) (frequency & 0x7f00) >> 8; - buf[1] = (u8 ) (frequency & 0x00ff) >> 0; + buf[0] = (u8) (frequency & 0x7f00) >> 8; + buf[1] = (u8) (frequency & 0x00ff) >> 0; buf[2] = 0x80 | 0x40 | 0x02; buf[3] = 0x00; @@ -178,7 +178,7 @@ static int tda665x_set_state(struct dvb_frontend *fe, goto exit; /* sleep for some time */ - printk("%s: Waiting to Phase LOCK\n", __func__); + printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__); msleep(20); /* check status */ err = tda665x_get_status(fe, &status); @@ -186,19 +186,19 @@ static int tda665x_set_state(struct dvb_frontend *fe, goto exit; if (status == 1) { - printk("%s: Tuner Phase locked: status=%d\n", __func__, status); + printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status); state->frequency = frequency; /* cache successful state */ } else { - printk("%s: No Phase lock: status=%d\n", __func__, status); + printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status); } } else { - printk("%s: Unknown parameter (param=%d)\n", __func__, param); + printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param); return -EINVAL; } return 0; exit: - printk("%s: I/O Error\n", __func__); + printk(KERN_ERR "%s: I/O Error\n", __func__); return err; } @@ -226,7 +226,7 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, struct tda665x_state *state = NULL; struct dvb_tuner_info *info; - state = kzalloc(sizeof (struct tda665x_state), GFP_KERNEL); + state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL); if (state == NULL) goto exit; @@ -237,12 +237,12 @@ struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, fe->ops.tuner_ops = tda665x_ops; info = &fe->ops.tuner_ops.info; - memcpy(info->name, config->name, sizeof (config->name)); + memcpy(info->name, config->name, sizeof(config->name)); info->frequency_min = config->frequency_min; info->frequency_max = config->frequency_max; info->frequency_step = config->frequency_offst; - printk("%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); + printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name); return fe; diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h index c0b544d8ef5..ec7927aa75a 100644 --- a/drivers/media/dvb/frontends/tda665x.h +++ b/drivers/media/dvb/frontends/tda665x.h @@ -40,7 +40,7 @@ extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, #else static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe, - const struct tda665x_config *config, + const struct tda665x_config *config, struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index 6d5d101f0ab..ca70149f3dd 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -137,7 +137,7 @@ static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_dev struct mantis_hwconfig *config; int err = 0; - mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); if (mantis == NULL) { printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); err = -ENOMEM; diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 88899ac96d6..2f3ba81eaa0 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -119,7 +119,7 @@ static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) struct mantis_pci *mantis = ca->ca_priv; dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); -// mantis_set_direction(mantis, 1); /* Enable TS through CAM */ +/* mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */ return 0; } @@ -148,7 +148,7 @@ int mantis_ca_init(struct mantis_pci *mantis) int ca_flags = 0, result; dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA"); - ca = kzalloc(sizeof (struct mantis_ca), GFP_KERNEL); + ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL); if (!ca) { dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting .."); result = -ENOMEM; diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index f3fefbbc876..a4250fad6ac 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -145,7 +145,7 @@ static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_dev struct mantis_hwconfig *config; int err = 0; - mantis = kzalloc(sizeof (struct mantis_pci), GFP_KERNEL); + mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL); if (mantis == NULL) { printk(KERN_ERR "%s ERROR: Out of memory\n", __func__); err = -ENOMEM; diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 52b3e9ebfcf..3ddc9ba8440 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -36,14 +36,16 @@ static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) .flags = 0, .buf = data, .len = 1 - },{ + }, { .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length }, }; - if ((err = i2c_transfer(&mantis->adapter, msg, 2)) < 0) { + + err = i2c_transfer(&mantis->adapter, msg, 2); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >", err, data[0], data[1]); @@ -65,7 +67,8 @@ static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length) .len = length }; - if ((err = i2c_transfer(&mantis->adapter, &msg, 1)) < 0) { + err = i2c_transfer(&mantis->adapter, &msg, 1); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >", err, length, data[0], data[1]); @@ -81,7 +84,8 @@ static int get_mac_address(struct mantis_pci *mantis) int err; mantis->mac_address[0] = 0x08; - if ((err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6)) < 0) { + err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error"); return err; @@ -106,25 +110,25 @@ struct mantis_hwconfig unknown_device = { static void mantis_load_config(struct mantis_pci *mantis) { switch (mantis->subsystem_device) { - case MANTIS_VP_1033_DVB_S: // VP-1033 + case MANTIS_VP_1033_DVB_S: /* VP-1033 */ mantis->hwconfig = &vp1033_mantis_config; break; - case MANTIS_VP_1034_DVB_S: // VP-1034 + case MANTIS_VP_1034_DVB_S: /* VP-1034 */ mantis->hwconfig = &vp1034_mantis_config; break; - case MANTIS_VP_1041_DVB_S2: // VP-1041 + case MANTIS_VP_1041_DVB_S2: /* VP-1041 */ case TECHNISAT_SKYSTAR_HD2: mantis->hwconfig = &vp1041_mantis_config; break; - case MANTIS_VP_2033_DVB_C: // VP-2033 + case MANTIS_VP_2033_DVB_C: /* VP-2033 */ mantis->hwconfig = &vp2033_mantis_config; break; - case MANTIS_VP_2040_DVB_C: // VP-2040 - case TERRATEC_CINERGY_C_PCI: // VP-2040 clone + case MANTIS_VP_2040_DVB_C: /* VP-2040 */ + case TERRATEC_CINERGY_C_PCI: /* VP-2040 clone */ case TECHNISAT_CABLESTAR_HD2: mantis->hwconfig = &vp2040_mantis_config; break; - case MANTIS_VP_3030_DVB_T: // VP-3030 + case MANTIS_VP_3030_DVB_T: /* VP-3030 */ mantis->hwconfig = &vp3030_mantis_config; break; default: @@ -149,23 +153,28 @@ int mantis_core_init(struct mantis_pci *mantis) mantis->pdev->irq, mantis->latency, mantis->mantis_addr, mantis->mantis_mmio); - if ((err = mantis_i2c_init(mantis)) < 0) { + err = mantis_i2c_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed"); return err; } - if ((err = get_mac_address(mantis)) < 0) { + err = get_mac_address(mantis); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed"); return err; } - if ((err = mantis_dma_init(mantis)) < 0) { + err = mantis_dma_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed"); return err; } - if ((err = mantis_dvb_init(mantis)) < 0) { + err = mantis_dvb_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed"); return err; } - if ((err = mantis_uart_init(mantis)) < 0) { + err = mantis_uart_init(mantis); + if (err < 0) { dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed"); return err; } @@ -191,7 +200,7 @@ int mantis_core_exit(struct mantis_pci *mantis) return 0; } -// Turn the given bit on or off. +/* Turn the given bit on or off. */ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) { u32 cur; @@ -207,14 +216,15 @@ void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value) udelay(100); } -//direction = 0 , no CI passthrough ; 1 , CI passthrough +/* direction = 0 , no CI passthrough ; 1 , CI passthrough */ void mantis_set_direction(struct mantis_pci *mantis, int direction) { u32 reg; reg = mmread(0x28); dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup"); - if (direction == 0x01) { //to CI + if (direction == 0x01) { + /* to CI */ reg |= 0x04; mmwrite(reg, 0x28); reg &= 0xff - 0x04; diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h index a8093940993..8511b0cebac 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -33,15 +33,15 @@ struct vendorname { - __u8 *sub_vendor_name; - __u32 sub_vendor_id; + u8 *sub_vendor_name; + u32 sub_vendor_id; }; struct devicetype { - __u8 *sub_device_name; - __u32 sub_device_id; - __u8 device_type; - __u32 type_flags; + u8 *sub_device_name; + u32 sub_device_id; + u8 device_type; + u32 type_flags; }; @@ -54,4 +54,4 @@ extern int mantis_i2c_exit(struct mantis_pci *mantis); extern int mantis_core_init(struct mantis_pci *mantis); extern int mantis_core_exit(struct mantis_pci *mantis); -#endif //__MANTIS_CORE_H +#endif /* __MANTIS_CORE_H */ diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index eab3645f7ac..adad1f37efd 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -43,10 +43,10 @@ #define RISC_IRQ (0x01 << 24) #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) -#define RISC_FLUSH() mantis->risc_pos = 0 -#define RISC_INSTR(opcode) mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode) +#define RISC_FLUSH() (mantis->risc_pos = 0) +#define RISC_INSTR(opcode) (mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode)) -#define MANTIS_BUF_SIZE 64 * 1024 +#define MANTIS_BUF_SIZE (64 * 1024) #define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE >> 4) #define MANTIS_BLOCK_COUNT (1 << 4) #define MANTIS_RISC_SIZE PAGE_SIZE @@ -158,7 +158,8 @@ int mantis_dma_init(struct mantis_pci *mantis) goto err; } - if ((err = mantis_calc_lines(mantis)) < 0) { + err = mantis_calc_lines(mantis); + if (err < 0) { dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed"); goto err; @@ -248,7 +249,7 @@ void mantis_dma_xfer(unsigned long data) dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", mantis->last_block, mantis->finished_block); - (config->ts_size ? dvb_dmx_swfilter_204: dvb_dmx_swfilter) + (config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; } diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 54bf4ea9efd..8982d6fdf6b 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -116,7 +116,6 @@ static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) if (mantis->feeds == 1) { dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma"); - printk("mantis start feed & dma\n"); mantis_dma_start(mantis); } @@ -137,7 +136,6 @@ static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) mantis->feeds--; if (mantis->feeds == 0) { dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma"); - printk("mantis stop feed and dma\n"); mantis_dma_stop(mantis); } @@ -204,9 +202,9 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) } mantis->fe_mem.source = DMX_MEMORY_FE; - result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx,&mantis->fe_mem); + result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem); if (result < 0) { - dprintk(MANTIS_ERROR, 1,"dvb_dmx_init failed, ERROR=%d", result); + dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); goto err3; } @@ -224,10 +222,6 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!"); goto err5; } else { -// if (mantis->dvb_adapter == NULL) { -// dprintk(MANTIS_ERROR, 1, "DVB adapter "); -// goto err5; -// } if (mantis->fe == NULL) { dprintk(MANTIS_ERROR, 1, "FE "); goto err5; @@ -277,7 +271,7 @@ int __devexit mantis_dvb_exit(struct mantis_pci *mantis) int err; if (mantis->fe) { -// mantis_ca_exit(mantis); + /* mantis_ca_exit(mantis); */ err = mantis_frontend_shutdown(mantis); if (err != 0) dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err); diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index 7bb4e78aa71..dd38b933353 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -225,7 +225,7 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) init_waitqueue_head(&mantis->i2c_wq); mutex_init(&mantis->i2c_lock); - strncpy(i2c_adapter->name, "Mantis I2C", sizeof (i2c_adapter->name)); + strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name)); i2c_set_adapdata(i2c_adapter, mantis); i2c_adapter->owner = THIS_MODULE; diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index b27d7759788..487d149c802 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -36,9 +36,9 @@ static struct ir_scancode mantis_ir_table[] = { { 0x29, KEY_POWER }, { 0x28, KEY_FAVORITES }, { 0x30, KEY_TEXT }, - { 0x17, KEY_INFO }, // Preview + { 0x17, KEY_INFO }, /* Preview */ { 0x23, KEY_EPG }, - { 0x3b, KEY_F22 },// Record List + { 0x3b, KEY_F22 }, /* Record List */ { 0x3c, KEY_1 }, { 0x3e, KEY_2 }, { 0x39, KEY_3 }, @@ -71,22 +71,22 @@ static struct ir_scancode mantis_ir_table[] = { { 0x1f, KEY_REWIND }, { 0x2d, KEY_FASTFORWARD }, - { 0x1e, KEY_PREVIOUS }, // Replay |< - { 0x1d, KEY_NEXT }, // Skip >| + { 0x1e, KEY_PREVIOUS }, /* Replay |< */ + { 0x1d, KEY_NEXT }, /* Skip >| */ - { 0x0b, KEY_CAMERA }, // Capture - { 0x0f, KEY_LANGUAGE }, // SAP - { 0x18, KEY_MODE }, // PIP - { 0x12, KEY_ZOOM }, // Full screen, + { 0x0b, KEY_CAMERA }, /* Capture */ + { 0x0f, KEY_LANGUAGE }, /* SAP */ + { 0x18, KEY_MODE }, /* PIP */ + { 0x12, KEY_ZOOM }, /* Full screen */ { 0x1c, KEY_SUBTITLE }, { 0x2f, KEY_MUTE }, - { 0x16, KEY_F20 }, // L/R, - { 0x38, KEY_F21 }, // Hibernate, + { 0x16, KEY_F20 }, /* L/R */ + { 0x38, KEY_F21 }, /* Hibernate */ - { 0x37, KEY_SWITCHVIDEOMODE }, // A/V - { 0x31, KEY_AGAIN }, // Recall, - { 0x1a, KEY_KPPLUS }, // Zoom+, - { 0x19, KEY_KPMINUS }, // Zoom-, + { 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */ + { 0x31, KEY_AGAIN }, /* Recall */ + { 0x1a, KEY_KPPLUS }, /* Zoom+ */ + { 0x19, KEY_KPMINUS }, /* Zoom- */ { 0x27, KEY_RED }, { 0x0C, KEY_GREEN }, { 0x01, KEY_YELLOW }, diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index 0072e149a56..c2f572b49fa 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -29,7 +29,7 @@ #define MANTIS_INT_RISCEN (0x01 << 27) #define MANTIS_INT_I2CRACK (0x01 << 26) -//#define MANTIS_INT_GPIF (0xff << 12) +/* #define MANTIS_INT_GPIF (0xff << 12) */ #define MANTIS_INT_PCMCIA7 (0x01 << 19) #define MANTIS_INT_PCMCIA6 (0x01 << 18) diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index c9760b00d0a..3c62be30bbb 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -93,7 +93,7 @@ int lgtdqcs001f_tuner_set(struct dvb_frontend *fe, u32 div; - struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof (buf) }; + struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)}; div = params->frequency / 250; @@ -140,12 +140,12 @@ int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe, aclk = 0xb4; bclk = 0x51; } - stv0299_writereg (fe, 0x13, aclk); - stv0299_writereg (fe, 0x14, bclk); + stv0299_writereg(fe, 0x13, aclk); + stv0299_writereg(fe, 0x14, bclk); - stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); - stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); - stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); + stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg(fe, 0x21, ratio & 0xf0); return 0; } diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 7ddd149b0fe..36486b53f67 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -62,7 +62,7 @@ int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN"); break; default: - dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); + dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32) voltage); return -EINVAL; } mmwrite(0x00, MANTIS_GPIF_DOUT); diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c index 368fc815a61..515346dd31d 100644 --- a/drivers/media/dvb/mantis/mantis_vp1041.c +++ b/drivers/media/dvb/mantis/mantis_vp1041.c @@ -44,7 +44,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { -// 0x0000000b , /* SYSREG */ + /* 0x0000000b, *//* SYSREG */ { STB0899_DEV_ID , 0x30 }, { STB0899_DISCNTRL1 , 0x32 }, { STB0899_DISCNTRL2 , 0x80 }, @@ -55,7 +55,7 @@ static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = { { STB0899_DISSTATUS , 0x20 }, { STB0899_DISF22 , 0x99 }, { STB0899_DISF22RX , 0xa8 }, - //SYSREG ? + /* SYSREG ? */ { STB0899_ACRPRESC , 0x11 }, { STB0899_ACRDIV1 , 0x0a }, { STB0899_ACRDIV2 , 0x05 }, @@ -323,9 +323,8 @@ static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend * vp1041_stb0899_config.demod_address); if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) { - if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) { - printk("%s: No LNBP21 found!\n", __func__); - } + if (!lnbp21_attach(mantis->fe, adapter, 0, 0)) + dprintk(MANTIS_ERROR, 1, "No LNBP21 found!"); } } else { return -EREMOTEIO; diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 45f71749bb9..07d468ff5e1 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -71,7 +71,7 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten struct i2c_adapter *adapter = &mantis->adapter; u8 buf[6]; - struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof (buf) }; + struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)}; int i; #define CU1216_IF 36125000 diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c index 8471bff672f..a7ca233e800 100644 --- a/drivers/media/dvb/mantis/mantis_vp2040.c +++ b/drivers/media/dvb/mantis/mantis_vp2040.c @@ -53,7 +53,7 @@ static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_fronten struct i2c_adapter *adapter = &mantis->adapter; u8 buf[6]; - struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof (buf) }; + struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)}; int i; #define CU1216_IF 36125000 -- cgit v1.2.3 From 28fddb7cd5b7a12b81c8ec1a358749e60760e741 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 09:01:27 -0300 Subject: V4L/DVB (13810): [MB86A16] Use DVB_* macros Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h index 68f25a64017..a88a6a1febf 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -31,8 +31,22 @@ struct mb86a16_config { int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage); }; + + +#if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE)) + extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, struct i2c_adapter *i2c_adap); +#else + +static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config, + struct i2c_adapter *i2c_adap) +{ + printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__); + return NULL; +} + +#endif /* CONFIG_DVB_MB86A16 */ #endif /* __MB86A16_H */ -- cgit v1.2.3 From 4cd191fba45ee3cf3035d7e4d3a942979cd9c5e4 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 09:04:59 -0300 Subject: V4L/DVB (13811): [MB86A16] Update Copyright header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/mb86a16.c | 2 +- drivers/media/dvb/frontends/mb86a16.h | 2 +- drivers/media/dvb/frontends/mb86a16_priv.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c index 32f20c68144..d05f7500e0c 100644 --- a/drivers/media/dvb/frontends/mb86a16.c +++ b/drivers/media/dvb/frontends/mb86a16.c @@ -1,7 +1,7 @@ /* Fujitsu MB86A16 DVB-S/DSS DC Receiver driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h index a88a6a1febf..6ea8c376394 100644 --- a/drivers/media/dvb/frontends/mb86a16.h +++ b/drivers/media/dvb/frontends/mb86a16.h @@ -1,7 +1,7 @@ /* Fujitsu MB86A16 DVB-S/DSS DC Receiver driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h index d8757fafcf1..360a35acfe8 100644 --- a/drivers/media/dvb/frontends/mb86a16_priv.h +++ b/drivers/media/dvb/frontends/mb86a16_priv.h @@ -1,7 +1,7 @@ /* Fujitsu MB86A16 DVB-S/DSS DC Receiver driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 -- cgit v1.2.3 From 8825a0970cef408fb2f1a44e3cb05d6ba41a18db Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 15 Dec 2009 09:13:49 -0300 Subject: V4L/DVB (13812): [Mantis/Hopper] Update Copyright header Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/hopper_cards.c | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/hopper_vp3028.c | 4 ++-- drivers/media/dvb/mantis/hopper_vp3028.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_ca.c | 2 +- drivers/media/dvb/mantis/mantis_ca.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_cards.c | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_common.h | 2 +- drivers/media/dvb/mantis/mantis_core.c | 2 +- drivers/media/dvb/mantis/mantis_core.h | 2 +- drivers/media/dvb/mantis/mantis_dma.c | 2 +- drivers/media/dvb/mantis/mantis_dma.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_dvb.c | 2 +- drivers/media/dvb/mantis/mantis_dvb.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_evm.c | 2 +- drivers/media/dvb/mantis/mantis_hif.c | 2 +- drivers/media/dvb/mantis/mantis_hif.h | 2 +- drivers/media/dvb/mantis/mantis_i2c.c | 2 +- drivers/media/dvb/mantis/mantis_i2c.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_ioc.c | 2 +- drivers/media/dvb/mantis/mantis_ioc.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_link.h | 2 +- drivers/media/dvb/mantis/mantis_pci.c | 2 +- drivers/media/dvb/mantis/mantis_pci.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_pcmcia.c | 2 +- drivers/media/dvb/mantis/mantis_reg.h | 2 +- drivers/media/dvb/mantis/mantis_uart.h | 2 +- drivers/media/dvb/mantis/mantis_vp1033.c | 2 +- drivers/media/dvb/mantis/mantis_vp1033.h | 2 +- drivers/media/dvb/mantis/mantis_vp1034.c | 2 +- drivers/media/dvb/mantis/mantis_vp1034.h | 2 +- drivers/media/dvb/mantis/mantis_vp2033.c | 2 +- drivers/media/dvb/mantis/mantis_vp2033.h | 2 +- drivers/media/dvb/mantis/mantis_vp3028.c | 2 +- drivers/media/dvb/mantis/mantis_vp3028.h | 20 ++++++++++++++++++++ drivers/media/dvb/mantis/mantis_vp3030.c | 2 +- drivers/media/dvb/mantis/mantis_vp3030.h | 2 +- 36 files changed, 227 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c index ca70149f3dd..d073c61e3c0 100644 --- a/drivers/media/dvb/mantis/hopper_cards.c +++ b/drivers/media/dvb/mantis/hopper_cards.c @@ -1,3 +1,23 @@ +/* + Hopper PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include #include diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c index 76cad876338..96674c78e86 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.c +++ b/drivers/media/dvb/mantis/hopper_vp3028.c @@ -1,7 +1,7 @@ /* - Mantis VP-3028 driver + Hopper VP-3028 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h index e8a3c2297bb..57239498bc8 100644 --- a/drivers/media/dvb/mantis/hopper_vp3028.h +++ b/drivers/media/dvb/mantis/hopper_vp3028.h @@ -1,3 +1,23 @@ +/* + Hopper VP-3028 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_VP3028_H #define __MANTIS_VP3028_H diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c index 2f3ba81eaa0..403ce043d00 100644 --- a/drivers/media/dvb/mantis/mantis_ca.c +++ b/drivers/media/dvb/mantis/mantis_ca.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h index b7e48ee1fac..dc63e55f7ec 100644 --- a/drivers/media/dvb/mantis/mantis_ca.h +++ b/drivers/media/dvb/mantis/mantis_ca.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_CA_H #define __MANTIS_CA_H diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c index a4250fad6ac..16f1708fd3b 100644 --- a/drivers/media/dvb/mantis/mantis_cards.c +++ b/drivers/media/dvb/mantis/mantis_cards.c @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #include #include #include diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h index c2d085460e6..d0b645a483c 100644 --- a/drivers/media/dvb/mantis/mantis_common.h +++ b/drivers/media/dvb/mantis/mantis_common.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c index 3ddc9ba8440..8113b23ce44 100644 --- a/drivers/media/dvb/mantis/mantis_core.c +++ b/drivers/media/dvb/mantis/mantis_core.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h index 8511b0cebac..833ee42e694 100644 --- a/drivers/media/dvb/mantis/mantis_core.h +++ b/drivers/media/dvb/mantis/mantis_core.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c index adad1f37efd..46202a4012a 100644 --- a/drivers/media/dvb/mantis/mantis_dma.c +++ b/drivers/media/dvb/mantis/mantis_dma.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h index 4cba8763536..6be00fa8209 100644 --- a/drivers/media/dvb/mantis/mantis_dma.h +++ b/drivers/media/dvb/mantis/mantis_dma.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_DMA_H #define __MANTIS_DMA_H diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index 8982d6fdf6b..99d82eec3b0 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -1,6 +1,6 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h index 31ebbb47df3..464199db304 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.h +++ b/drivers/media/dvb/mantis/mantis_dvb.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_DVB_H #define __MANTIS_DVB_H diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c index 9304b0edd89..a7b369a439d 100644 --- a/drivers/media/dvb/mantis/mantis_evm.c +++ b/drivers/media/dvb/mantis/mantis_evm.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c index 73e5ca0c6c1..7477dac628b 100644 --- a/drivers/media/dvb/mantis/mantis_hif.c +++ b/drivers/media/dvb/mantis/mantis_hif.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h index f960c0aeacc..9094f9ed236 100644 --- a/drivers/media/dvb/mantis/mantis_hif.h +++ b/drivers/media/dvb/mantis/mantis_hif.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index dd38b933353..b7df345fe22 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h index d40da4fa000..1342df2faed 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.h +++ b/drivers/media/dvb/mantis/mantis_i2c.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_I2C_H #define __MANTIS_I2C_H diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c index dd6636999ad..de148ded52d 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.c +++ b/drivers/media/dvb/mantis/mantis_ioc.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h index 20526406723..188fe5a8161 100644 --- a/drivers/media/dvb/mantis/mantis_ioc.h +++ b/drivers/media/dvb/mantis/mantis_ioc.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_IOC_H #define __MANTIS_IOC_H diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h index f6030c9fba2..2a814774a00 100644 --- a/drivers/media/dvb/mantis/mantis_link.h +++ b/drivers/media/dvb/mantis/mantis_link.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 5165a390e07..5e4f57615ad 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h index 5ce776ffcb3..65f00451908 100644 --- a/drivers/media/dvb/mantis/mantis_pci.h +++ b/drivers/media/dvb/mantis/mantis_pci.h @@ -1,3 +1,23 @@ +/* + Mantis PCI bridge driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_PCI_H #define __MANTIS_PCI_H diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c index d6bca3e5859..5cb545b913f 100644 --- a/drivers/media/dvb/mantis/mantis_pcmcia.c +++ b/drivers/media/dvb/mantis/mantis_pcmcia.c @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h index c2f572b49fa..7761f9dc7fe 100644 --- a/drivers/media/dvb/mantis/mantis_reg.h +++ b/drivers/media/dvb/mantis/mantis_reg.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h index 62ab66ebb97..ffb62a0a5a1 100644 --- a/drivers/media/dvb/mantis/mantis_uart.h +++ b/drivers/media/dvb/mantis/mantis_uart.h @@ -1,7 +1,7 @@ /* Mantis PCI bridge driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c index 3c62be30bbb..4a723bda003 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.c +++ b/drivers/media/dvb/mantis/mantis_vp1033.c @@ -1,7 +1,7 @@ /* Mantis VP-1033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h index 2c18d215324..7daaa1bf127 100644 --- a/drivers/media/dvb/mantis/mantis_vp1033.h +++ b/drivers/media/dvb/mantis/mantis_vp1033.h @@ -1,7 +1,7 @@ /* Mantis VP-1033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c index 36486b53f67..8e6ae558ee5 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.c +++ b/drivers/media/dvb/mantis/mantis_vp1034.c @@ -1,7 +1,7 @@ /* Mantis VP-1034 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h index 30269129066..323f38ef8e3 100644 --- a/drivers/media/dvb/mantis/mantis_vp1034.h +++ b/drivers/media/dvb/mantis/mantis_vp1034.h @@ -1,7 +1,7 @@ /* Mantis VP-1034 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c index 07d468ff5e1..10ce81790a8 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.c +++ b/drivers/media/dvb/mantis/mantis_vp2033.c @@ -1,7 +1,7 @@ /* Mantis VP-2033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h index e6c5fe80f72..c55242b79d5 100644 --- a/drivers/media/dvb/mantis/mantis_vp2033.h +++ b/drivers/media/dvb/mantis/mantis_vp2033.h @@ -1,7 +1,7 @@ /* Mantis VP-2033 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c index 7f8918c2ce6..4155c838a18 100644 --- a/drivers/media/dvb/mantis/mantis_vp3028.c +++ b/drivers/media/dvb/mantis/mantis_vp3028.c @@ -1,7 +1,7 @@ /* Mantis VP-3028 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h index c51628ddf3c..b07be6adc52 100644 --- a/drivers/media/dvb/mantis/mantis_vp3028.h +++ b/drivers/media/dvb/mantis/mantis_vp3028.h @@ -1,3 +1,23 @@ +/* + Mantis VP-3028 driver + + Copyright (C) Manu Abraham (abraham.manu@gmail.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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + #ifndef __MANTIS_VP3028_H #define __MANTIS_VP3028_H diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c index 1895e956b16..1f433421495 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.c +++ b/drivers/media/dvb/mantis/mantis_vp3030.c @@ -1,7 +1,7 @@ /* Mantis VP-3030 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h index 0a110ba5c1d..5f12c426627 100644 --- a/drivers/media/dvb/mantis/mantis_vp3030.h +++ b/drivers/media/dvb/mantis/mantis_vp3030.h @@ -1,7 +1,7 @@ /* Mantis VP-3030 driver - Copyright (C) 2005, 2006 Manu Abraham (abraham.manu@gmail.com) + Copyright (C) Manu Abraham (abraham.manu@gmail.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 -- cgit v1.2.3 From 9c0832e3990b541ea1b8f5d44fe4c204a5e7d396 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 16 Dec 2009 23:57:27 -0200 Subject: V4L/DVB(13808a): mantis: convert it to the new ir-core register/unregister functions Fix a merge conflict between mantis and IR cleanups Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_input.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c index 487d149c802..6a9df779441 100644 --- a/drivers/media/dvb/mantis/mantis_input.c +++ b/drivers/media/dvb/mantis/mantis_input.c @@ -118,7 +118,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->name = name; rc->phys = dev; - ir_input_init(rc, &rc_state, IR_TYPE_OTHER, &ir_mantis); + ir_input_init(rc, &rc_state, IR_TYPE_OTHER); rc->id.bustype = BUS_PCI; rc->id.vendor = mantis->vendor_id; @@ -126,7 +126,7 @@ int mantis_input_init(struct mantis_pci *mantis) rc->id.version = 1; rc->dev = mantis->pdev->dev; - err = input_register_device(rc); + err = ir_input_register(rc, &ir_mantis); if (err) { dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err); input_free_device(rc); @@ -142,7 +142,7 @@ int mantis_exit(struct mantis_pci *mantis) { struct input_dev *rc = mantis->rc; - input_unregister_device(rc); + ir_input_unregister(rc); return 0; } -- cgit v1.2.3 From 8873c61f1fe849bc8719839ddfa3300266f8bc39 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 5 Dec 2009 01:24:08 -0300 Subject: V4L/DVB (13808): [Mantis/Hopper] Build update for Mantis/Hopper based cards Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 4 ++++ drivers/media/dvb/Makefile | 14 +++++++++++++- drivers/media/dvb/frontends/Kconfig | 8 ++++++++ drivers/media/dvb/frontends/Makefile | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 35d0817126e..cf8f65f309d 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -72,6 +72,10 @@ comment "Supported Earthsoft PT1 Adapters" depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/pt1/Kconfig" +comment "Supported Mantis Adapters" + depends on DVB_CORE && PCI && I2C + source "drivers/media/dvb/mantis/Kconfig" + comment "Supported DVB Frontends" depends on DVB_CORE source "drivers/media/dvb/frontends/Kconfig" diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile index 16d262ddb45..c12922c3659 100644 --- a/drivers/media/dvb/Makefile +++ b/drivers/media/dvb/Makefile @@ -2,6 +2,18 @@ # Makefile for the kernel multimedia device drivers. # -obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ pt1/ +obj-y := dvb-core/ \ + frontends/ \ + ttpci/ \ + ttusb-dec/ \ + ttusb-budget/ \ + b2c2/ \ + bt8xx/ \ + dvb-usb/ \ + pluto2/ \ + siano/ \ + dm1105/ \ + pt1/ \ + mantis/ obj-$(CONFIG_DVB_FIREDTV) += firewire/ diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 7820ca084b1..cd7f9b7cbff 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -208,6 +208,14 @@ config DVB_DS3000 help A DVB-S/S2 tuner module. Say Y when you want to support this frontend. +config DVB_MB86A16 + tristate "Fujitsu MB86A16 based" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A DVB-S/DSS Direct Conversion reveiver. + Say Y when you want to support this frontend. + comment "DVB-T (terrestrial) frontends" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 59f7b880355..874e8ada4d1 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -81,3 +81,4 @@ obj-$(CONFIG_DVB_STV6110x) += stv6110x.o obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o obj-$(CONFIG_DVB_DS3000) += ds3000.o +obj-$(CONFIG_DVB_MB86A16) += mb86a16.o -- cgit v1.2.3 From 184ac7535ee078a4572b668a348134d67c3977d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Dec 2009 00:06:04 -0200 Subject: V4L/DVB (13808b): mantis: replace DMA_nnBIT_MASK to DMA_BIT_MASK(32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/media/dvb/mantis/mantis_pci.c: In function ‘mantis_pci_init’: drivers/media/dvb/mantis/mantis_pci.c:76: warning: ‘DMA_nnBIT_MASK’ is deprecated Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index 5e4f57615ad..e7cd8aabd88 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -73,7 +73,7 @@ int __devinit mantis_pci_init(struct mantis_pci *mantis) goto fail0; } - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (err != 0) { dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err); ret = -ENOMEM; -- cgit v1.2.3 From 4cf0b3f130a4fe573077e4d0237fd3dd0f67d3f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 18 Dec 2009 09:58:46 -0200 Subject: V4L/DVB(13824a): mantis: Fix __devexit bad annotations WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x13d7): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x1433): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x185e): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/mantis/built-in.o(.devinit.text+0x18ba): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x68b8): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x6914): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x6d3f): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/dvb/built-in.o(.devinit.text+0x6d9b): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14634): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14690): Section mismatch in reference from the function mantis_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit mantis_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14abb): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_i2c_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_i2c_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_i2c_exit() so it may be used outside an exit section. WARNING: drivers/media/built-in.o(.devinit.text+0x14b17): Section mismatch in reference from the function hopper_pci_probe() to the function .devexit.text:mantis_pci_exit() The function __devinit hopper_pci_probe() references a function __devexit mantis_pci_exit(). This is often seen when error handling in the init function uses functionality in the exit path. The fix is often to remove the __devexit annotation of mantis_pci_exit() so it may be used outside an exit section. Acked-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/mantis_i2c.c | 2 +- drivers/media/dvb/mantis/mantis_pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c index b7df345fe22..7870bcf9689 100644 --- a/drivers/media/dvb/mantis/mantis_i2c.c +++ b/drivers/media/dvb/mantis/mantis_i2c.c @@ -253,7 +253,7 @@ int __devinit mantis_i2c_init(struct mantis_pci *mantis) } EXPORT_SYMBOL_GPL(mantis_i2c_init); -int __devexit mantis_i2c_exit(struct mantis_pci *mantis) +int mantis_i2c_exit(struct mantis_pci *mantis) { u32 intmask; diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c index e7cd8aabd88..6c7534af6b4 100644 --- a/drivers/media/dvb/mantis/mantis_pci.c +++ b/drivers/media/dvb/mantis/mantis_pci.c @@ -155,7 +155,7 @@ fail0: } EXPORT_SYMBOL_GPL(mantis_pci_init); -void __devexit mantis_pci_exit(struct mantis_pci *mantis) +void mantis_pci_exit(struct mantis_pci *mantis) { struct pci_dev *pdev = mantis->pdev; -- cgit v1.2.3 From fcd89de3bd1c8735f9b7c759dc4848ab6e525bb9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 19 Dec 2009 14:11:50 -0300 Subject: V4L/DVB (13851): Fix Input dependency for Mantis > > > > CONFIG_INPUT=n As reported by Randy Dunlap : > ERROR: "ir_input_register" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "ir_input_unregister" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "ir_input_init" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "input_free_device" [drivers/media/dvb/mantis/mantis_core.ko] undefined! > ERROR: "input_allocate_device" [drivers/media/dvb/mantis/mantis_core.ko] undefined! Signed-off-by: Manu Abraham Acked-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/mantis/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig index f9219cd7bb0..f7b72a32adf 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 + depends on PCI && I2C && INPUT help Support for PCI cards based on the Mantis and Hopper PCi bridge. -- cgit v1.2.3 From 6f2af72a2451b7491fba820b1d1b0b91c6a84027 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 5 Jan 2010 13:59:06 +0000 Subject: mfd: WM8350 off by one bug If irq == WM8350_NUM_IRQ that would put us past the end of the array. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-irq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c index c8df547c474..9025f29e270 100644 --- a/drivers/mfd/wm8350-irq.c +++ b/drivers/mfd/wm8350-irq.c @@ -434,7 +434,7 @@ int wm8350_register_irq(struct wm8350 *wm8350, int irq, irq_handler_t handler, unsigned long flags, const char *name, void *data) { - if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) + if (irq < 0 || irq >= WM8350_NUM_IRQ || !handler) return -EINVAL; if (wm8350->irq[irq].handler) @@ -453,7 +453,7 @@ EXPORT_SYMBOL_GPL(wm8350_register_irq); int wm8350_free_irq(struct wm8350 *wm8350, int irq) { - if (irq < 0 || irq > WM8350_NUM_IRQ) + if (irq < 0 || irq >= WM8350_NUM_IRQ) return -EINVAL; wm8350_mask_irq(wm8350, irq); -- cgit v1.2.3 From 64e8867ba8098b69889c1af94997a5ba2348fb26 Mon Sep 17 00:00:00 2001 From: Ian Molton Date: Wed, 6 Jan 2010 13:51:48 +0100 Subject: mfd: tmio_mmc hardware abstraction for CNF area This patch abstracts out the CNF area code from tmio_mmc which is not present in all hardware that can use this driver. This is required so that we can support non-toshiba based hardware. ASIC3 support by Philipp Zabel Signed-off-by: Ian Molton Signed-off-by: Magnus Damm Signed-off-by: Samuel Ortiz --- drivers/mfd/Makefile | 6 +-- drivers/mfd/asic3.c | 40 ++++++++++++--- drivers/mfd/t7l66xb.c | 55 +++++++++++++------- drivers/mfd/tc6387xb.c | 119 ++++++++++++++++++++++++++++++++------------ drivers/mfd/tc6393xb.c | 56 +++++++++++++++++---- drivers/mfd/tmio_core.c | 52 +++++++++++++++++++ drivers/mmc/host/tmio_mmc.c | 59 +++++++--------------- drivers/mmc/host/tmio_mmc.h | 46 +++-------------- 8 files changed, 284 insertions(+), 149 deletions(-) create mode 100644 drivers/mfd/tmio_core.c (limited to 'drivers') diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index ca2f2c4ff05..8f0d18409ed 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -11,9 +11,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o -obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o -obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o -obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o +obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o +obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o +obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index e22128c3e9a..95c1e6bd172 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -80,6 +80,7 @@ struct asic3 { u16 irq_bothedge[4]; struct gpio_chip gpio; struct device *dev; + void __iomem *tmio_cnf; struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)]; }; @@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = { .resources = ds1wm_resources, }; +static void asic3_mmc_pwr(struct platform_device *pdev, int state) +{ + struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); + + tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state); +} + +static void asic3_mmc_clk_div(struct platform_device *pdev, int state) +{ + struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); + + tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state); +} + static struct tmio_mmc_data asic3_mmc_data = { - .hclk = 24576000, + .hclk = 24576000, + .set_pwr = asic3_mmc_pwr, + .set_clk_div = asic3_mmc_clk_div, }; static struct resource asic3_mmc_resources[] = { @@ -695,11 +712,6 @@ static struct resource asic3_mmc_resources[] = { .end = ASIC3_SD_CTRL_BASE + 0x3ff, .flags = IORESOURCE_MEM, }, - { - .start = ASIC3_SD_CONFIG_BASE, - .end = ASIC3_SD_CONFIG_BASE + 0x1ff, - .flags = IORESOURCE_MEM, - }, { .start = 0, .end = 0, @@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev) asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), ASIC3_SDHWCTRL_SDPWR, 1); + /* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */ + tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift, + ASIC3_SD_CTRL_BASE >> 1); + return 0; } @@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm); /* MMC */ + asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) + + mem_sdio->start, 0x400 >> asic->bus_shift); + if (!asic->tmio_cnf) { + ret = -ENOMEM; + dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n"); + goto out; + } asic3_mmc_resources[0].start >>= asic->bus_shift; asic3_mmc_resources[0].end >>= asic->bus_shift; - asic3_mmc_resources[1].start >>= asic->bus_shift; - asic3_mmc_resources[1].end >>= asic->bus_shift; asic3_cell_mmc.platform_data = &asic3_cell_mmc; asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc); @@ -820,7 +841,10 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, static void asic3_mfd_remove(struct platform_device *pdev) { + struct asic3 *asic = platform_get_drvdata(pdev); + mfd_remove_devices(&pdev->dev); + iounmap(asic->tmio_cnf); } /* Core */ diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 0a255c1f1ce..bcf4687d4af 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c @@ -38,6 +38,19 @@ enum { T7L66XB_CELL_MMC, }; +static const struct resource t7l66xb_mmc_resources[] = { + { + .start = 0x800, + .end = 0x9ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_T7L66XB_MMC, + .end = IRQ_T7L66XB_MMC, + .flags = IORESOURCE_IRQ, + }, +}; + #define SCR_REVID 0x08 /* b Revision ID */ #define SCR_IMR 0x42 /* b Interrupt Mask */ #define SCR_DEV_CTL 0xe0 /* b Device control */ @@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc) spin_unlock_irqrestore(&t7l66xb->lock, flags); + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0, + t7l66xb_mmc_resources[0].start & 0xfffe); + return 0; } @@ -106,28 +122,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc) return 0; } +static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state); +} + +static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct t7l66xb *t7l66xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state); +} + /*--------------------------------------------------------------------------*/ static struct tmio_mmc_data t7166xb_mmc_data = { .hclk = 24000000, -}; - -static const struct resource t7l66xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_T7L66XB_MMC, - .end = IRQ_T7L66XB_MMC, - .flags = IORESOURCE_IRQ, - }, + .set_pwr = t7l66xb_mmc_pwr, + .set_clk_div = t7l66xb_mmc_clk_div, }; static const struct resource t7l66xb_nand_resources[] = { @@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev) if (pdata && pdata->resume) pdata->resume(dev); + tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0, + t7l66xb_mmc_resources[0].start & 0xfffe); + return 0; } #else diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index 3280ab33f88..5c7f04343d5 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c @@ -22,28 +22,52 @@ enum { TC6387XB_CELL_MMC, }; +struct tc6387xb { + void __iomem *scr; + struct clk *clk32k; + struct resource rscr; +}; + +static struct resource tc6387xb_mmc_resources[] = { + { + .start = 0x800, + .end = 0x9ff, + .flags = IORESOURCE_MEM, + }, + { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +/*--------------------------------------------------------------------------*/ + #ifdef CONFIG_PM static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state) { - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); struct tc6387xb_platform_data *pdata = dev->dev.platform_data; if (pdata && pdata->suspend) pdata->suspend(dev); - clk_disable(clk32k); + clk_disable(tc6387xb->clk32k); return 0; } static int tc6387xb_resume(struct platform_device *dev) { - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); struct tc6387xb_platform_data *pdata = dev->dev.platform_data; - clk_enable(clk32k); + clk_enable(tc6387xb->clk32k); if (pdata && pdata->resume) pdata->resume(dev); + tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0, + tc6387xb_mmc_resources[0].start & 0xfffe); + return 0; } #else @@ -53,12 +77,32 @@ static int tc6387xb_resume(struct platform_device *dev) /*--------------------------------------------------------------------------*/ +static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state); +} + +static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state); +} + + static int tc6387xb_mmc_enable(struct platform_device *mmc) { struct platform_device *dev = to_platform_device(mmc->dev.parent); - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - clk_enable(clk32k); + clk_enable(tc6387xb->clk32k); + + tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0, + tc6387xb_mmc_resources[0].start & 0xfffe); return 0; } @@ -66,36 +110,20 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc) static int tc6387xb_mmc_disable(struct platform_device *mmc) { struct platform_device *dev = to_platform_device(mmc->dev.parent); - struct clk *clk32k = platform_get_drvdata(dev); + struct tc6387xb *tc6387xb = platform_get_drvdata(dev); - clk_disable(clk32k); + clk_disable(tc6387xb->clk32k); return 0; } -/*--------------------------------------------------------------------------*/ - static struct tmio_mmc_data tc6387xb_mmc_data = { .hclk = 24000000, + .set_pwr = tc6387xb_mmc_pwr, + .set_clk_div = tc6387xb_mmc_clk_div, }; -static struct resource tc6387xb_mmc_resources[] = { - { - .start = 0x800, - .end = 0x9ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, - { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ, - }, -}; +/*--------------------------------------------------------------------------*/ static struct mfd_cell tc6387xb_cells[] = { [TC6387XB_CELL_MMC] = { @@ -111,8 +139,9 @@ static struct mfd_cell tc6387xb_cells[] = { static int tc6387xb_probe(struct platform_device *dev) { struct tc6387xb_platform_data *pdata = dev->dev.platform_data; - struct resource *iomem; + struct resource *iomem, *rscr; struct clk *clk32k; + struct tc6387xb *tc6387xb; int irq, ret; iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -120,18 +149,40 @@ static int tc6387xb_probe(struct platform_device *dev) return -EINVAL; } + tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL); + if (!tc6387xb) + return -ENOMEM; + ret = platform_get_irq(dev, 0); if (ret >= 0) irq = ret; else - goto err_resource; + goto err_no_irq; clk32k = clk_get(&dev->dev, "CLK_CK32K"); if (IS_ERR(clk32k)) { ret = PTR_ERR(clk32k); + goto err_no_clk; + } + + rscr = &tc6387xb->rscr; + rscr->name = "tc6387xb-core"; + rscr->start = iomem->start; + rscr->end = iomem->start + 0xff; + rscr->flags = IORESOURCE_MEM; + + ret = request_resource(iomem, rscr); + if (ret) goto err_resource; + + tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1); + if (!tc6387xb->scr) { + ret = -ENOMEM; + goto err_ioremap; } - platform_set_drvdata(dev, clk32k); + + tc6387xb->clk32k = clk32k; + platform_set_drvdata(dev, tc6387xb); if (pdata && pdata->enable) pdata->enable(dev); @@ -149,8 +200,13 @@ static int tc6387xb_probe(struct platform_device *dev) if (!ret) return 0; - clk_put(clk32k); +err_ioremap: + release_resource(&tc6387xb->rscr); err_resource: + clk_put(clk32k); +err_no_clk: +err_no_irq: + kfree(tc6387xb); return ret; } @@ -195,3 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton"); MODULE_ALIAS("platform:tc6387xb"); + diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 1429a7341a9..4bc5a08a2b0 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c @@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand) return 0; } -static struct tmio_mmc_data tc6393xb_mmc_data = { - .hclk = 24000000, -}; - static struct resource __devinitdata tc6393xb_nand_resources[] = { { .start = 0x1000, @@ -164,11 +160,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = { .end = 0x9ff, .flags = IORESOURCE_MEM, }, - { - .start = 0x200, - .end = 0x2ff, - .flags = IORESOURCE_MEM, - }, { .start = IRQ_TC6393_MMC, .end = IRQ_TC6393_MMC, @@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb, } EXPORT_SYMBOL(tc6393xb_lcd_mode); +static int tc6393xb_mmc_enable(struct platform_device *mmc) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0, + tc6393xb_mmc_resources[0].start & 0xfffe); + + return 0; +} + +static int tc6393xb_mmc_resume(struct platform_device *mmc) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0, + tc6393xb_mmc_resources[0].start & 0xfffe); + + return 0; +} + +static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state); +} + +static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state) +{ + struct platform_device *dev = to_platform_device(mmc->dev.parent); + struct tc6393xb *tc6393xb = platform_get_drvdata(dev); + + tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state); +} + +static struct tmio_mmc_data tc6393xb_mmc_data = { + .hclk = 24000000, + .set_pwr = tc6393xb_mmc_pwr, + .set_clk_div = tc6393xb_mmc_clk_div, +}; + static struct mfd_cell __devinitdata tc6393xb_cells[] = { [TC6393XB_CELL_NAND] = { .name = "tmio-nand", @@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { }, [TC6393XB_CELL_MMC] = { .name = "tmio-mmc", + .enable = tc6393xb_mmc_enable, + .resume = tc6393xb_mmc_resume, .driver_data = &tc6393xb_mmc_data, .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), .resources = tc6393xb_mmc_resources, @@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer"); MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller"); MODULE_ALIAS("platform:tc6393xb"); + diff --git a/drivers/mfd/tmio_core.c b/drivers/mfd/tmio_core.c new file mode 100644 index 00000000000..eddc19ae464 --- /dev/null +++ b/drivers/mfd/tmio_core.c @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2009 Ian Molton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base) +{ + /* Enable the MMC/SD Control registers */ + sd_config_write16(cnf, shift, CNF_CMD, SDCREN); + sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe); + + /* Disable SD power during suspend */ + sd_config_write8(cnf, shift, CNF_PWR_CTL_3, 0x01); + + /* The below is required but why? FIXME */ + sd_config_write8(cnf, shift, CNF_STOP_CLK_CTL, 0x1f); + + /* Power down SD bus */ + sd_config_write8(cnf, shift, CNF_PWR_CTL_2, 0x00); + + return 0; +} +EXPORT_SYMBOL(tmio_core_mmc_enable); + +int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base) +{ + + /* Enable the MMC/SD Control registers */ + sd_config_write16(cnf, shift, CNF_CMD, SDCREN); + sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe); + + return 0; +} +EXPORT_SYMBOL(tmio_core_mmc_resume); + +void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state) +{ + sd_config_write8(cnf, shift, CNF_PWR_CTL_2, state ? 0x02 : 0x00); +} +EXPORT_SYMBOL(tmio_core_mmc_pwr); + +void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state) +{ + sd_config_write8(cnf, shift, CNF_SD_CLK_MODE, state ? 1 : 0); +} +EXPORT_SYMBOL(tmio_core_mmc_clk_div); + diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 7cccc852374..e22c3fa3516 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) clk |= 0x100; } - sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22); + if (host->set_clk_div) + host->set_clk_div(host->pdev, (clk>>22) & 1); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff); } @@ -427,12 +429,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Power sequence - OFF -> ON -> UP */ switch (ios->power_mode) { case MMC_POWER_OFF: /* power down SD bus */ - sd_config_write8(host, CNF_PWR_CTL_2, 0x00); + if (host->set_pwr) + host->set_pwr(host->pdev, 0); tmio_mmc_clk_stop(host); break; case MMC_POWER_ON: /* power up SD bus */ - - sd_config_write8(host, CNF_PWR_CTL_2, 0x02); + if (host->set_pwr) + host->set_pwr(host->pdev, 1); break; case MMC_POWER_UP: /* start bus clock */ tmio_mmc_clk_start(host); @@ -485,21 +488,15 @@ static int tmio_mmc_resume(struct platform_device *dev) { struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; struct mmc_host *mmc = platform_get_drvdata(dev); - struct tmio_mmc_host *host = mmc_priv(mmc); int ret = 0; /* Tell the MFD core we are ready to be enabled */ - if (cell->enable) { - ret = cell->enable(dev); + if (cell->resume) { + ret = cell->resume(dev); if (ret) goto out; } - /* Enable the MMC/SD Control registers */ - sd_config_write16(host, CNF_CMD, SDCREN); - sd_config_write32(host, CNF_CTL_BASE, - (dev->resource[0].start >> host->bus_shift) & 0xfffe); - mmc_resume_host(mmc); out: @@ -514,17 +511,16 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) { struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; struct tmio_mmc_data *pdata; - struct resource *res_ctl, *res_cnf; + struct resource *res_ctl; struct tmio_mmc_host *host; struct mmc_host *mmc; int ret = -EINVAL; - if (dev->num_resources != 3) + if (dev->num_resources != 2) goto out; res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0); - res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1); - if (!res_ctl || !res_cnf) + if (!res_ctl) goto out; pdata = cell->driver_data; @@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) host = mmc_priv(mmc); host->mmc = mmc; + host->pdev = dev; platform_set_drvdata(dev, mmc); + host->set_pwr = pdata->set_pwr; + host->set_clk_div = pdata->set_clk_div; + /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ host->bus_shift = resource_size(res_ctl) >> 10; @@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (!host->ctl) goto host_free; - host->cnf = ioremap(res_cnf->start, resource_size(res_cnf)); - if (!host->cnf) - goto unmap_ctl; - mmc->ops = &tmio_mmc_ops; mmc->caps = MMC_CAP_4_BIT_DATA; mmc->f_max = pdata->hclk; @@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (cell->enable) { ret = cell->enable(dev); if (ret) - goto unmap_cnf; + goto unmap_ctl; } - /* Enable the MMC/SD Control registers */ - sd_config_write16(host, CNF_CMD, SDCREN); - sd_config_write32(host, CNF_CTL_BASE, - (dev->resource[0].start >> host->bus_shift) & 0xfffe); - - /* Disable SD power during suspend */ - sd_config_write8(host, CNF_PWR_CTL_3, 0x01); - - /* The below is required but why? FIXME */ - sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f); - - /* Power down SD bus*/ - sd_config_write8(host, CNF_PWR_CTL_2, 0x00); - tmio_mmc_clk_stop(host); reset(host); @@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) if (ret >= 0) host->irq = ret; else - goto unmap_cnf; + goto unmap_ctl; disable_mmc_irqs(host, TMIO_MASK_ALL); ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); if (ret) - goto unmap_cnf; + goto unmap_ctl; mmc_add_host(mmc); @@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) return 0; -unmap_cnf: - iounmap(host->cnf); unmap_ctl: iounmap(host->ctl); host_free: @@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev) mmc_remove_host(mmc); free_irq(host->irq, host); iounmap(host->ctl); - iounmap(host->cnf); mmc_free_host(mmc); } diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 9fa99859497..692dc23363b 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -11,26 +11,6 @@ #include -#define CNF_CMD 0x04 -#define CNF_CTL_BASE 0x10 -#define CNF_INT_PIN 0x3d -#define CNF_STOP_CLK_CTL 0x40 -#define CNF_GCLK_CTL 0x41 -#define CNF_SD_CLK_MODE 0x42 -#define CNF_PIN_STATUS 0x44 -#define CNF_PWR_CTL_1 0x48 -#define CNF_PWR_CTL_2 0x49 -#define CNF_PWR_CTL_3 0x4a -#define CNF_CARD_DETECT_MODE 0x4c -#define CNF_SD_SLOT 0x50 -#define CNF_EXT_GCLK_CTL_1 0xf0 -#define CNF_EXT_GCLK_CTL_2 0xf1 -#define CNF_EXT_GCLK_CTL_3 0xf9 -#define CNF_SD_LED_EN_1 0xfa -#define CNF_SD_LED_EN_2 0xfe - -#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/ - #define CTL_SD_CMD 0x00 #define CTL_ARG_REG 0x04 #define CTL_STOP_INTERNAL_ACTION 0x08 @@ -110,7 +90,6 @@ struct tmio_mmc_host { - void __iomem *cnf; void __iomem *ctl; unsigned long bus_shift; struct mmc_command *cmd; @@ -119,10 +98,16 @@ struct tmio_mmc_host { struct mmc_host *mmc; int irq; + /* Callbacks for clock / power control */ + void (*set_pwr)(struct platform_device *host, int state); + void (*set_clk_div)(struct platform_device *host, int state); + /* pio related stuff */ struct scatterlist *sg_ptr; unsigned int sg_len; unsigned int sg_off; + + struct platform_device *pdev; }; #include @@ -163,25 +148,6 @@ static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); } -static inline void sd_config_write8(struct tmio_mmc_host *host, int addr, - u8 val) -{ - writeb(val, host->cnf + (addr << host->bus_shift)); -} - -static inline void sd_config_write16(struct tmio_mmc_host *host, int addr, - u16 val) -{ - writew(val, host->cnf + (addr << host->bus_shift)); -} - -static inline void sd_config_write32(struct tmio_mmc_host *host, int addr, - u32 val) -{ - writew(val, host->cnf + (addr << host->bus_shift)); - writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift)); -} - #include #include -- cgit v1.2.3 From 8e6ba2dfa2d6c4691a83a63e211990a8bd7b788b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 7 Jan 2010 16:16:14 +0000 Subject: mfd: WM835x GPIO direction register is not locked No need to set the security key when writing to it. Signed-off-by: Mark Brown Cc: stable@kernel.org Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 8485a701806..9a970bd6877 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -134,8 +134,7 @@ static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) return 0; - if ((reg == WM8350_GPIO_CONFIGURATION_I_O) || - (reg >= WM8350_GPIO_FUNCTION_SELECT_1 && + if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 && reg <= WM8350_GPIO_FUNCTION_SELECT_4) || (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) -- cgit v1.2.3 From 1e02b2c32484bfe0c5564d9be060b7d9821307b9 Mon Sep 17 00:00:00 2001 From: Alberto Panizzo Date: Mon, 14 Dec 2009 18:18:05 +0100 Subject: mfd: Unlock mc13783 before subsystems initialisation, at probe time. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this, mc13783 subsystems drivers can configure the mc13783 chip reading and writing registers. Signed-off-by: Alberto Panizzo Acked-by: Uwe Kleine-König Signed-off-by: Samuel Ortiz --- drivers/mfd/mc13783-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index a1ade2324ea..735c8a4d164 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c @@ -619,6 +619,8 @@ err_revision: } /* This should go away (END) */ + mc13783_unlock(mc13783); + if (pdata->flags & MC13783_USE_ADC) mc13783_add_subdevice(mc13783, "mc13783-adc"); @@ -641,8 +643,6 @@ err_revision: if (pdata->flags & MC13783_USE_TOUCHSCREEN) mc13783_add_subdevice(mc13783, "mc13783-ts"); - mc13783_unlock(mc13783); - return 0; } -- cgit v1.2.3 From 1152dcc28c66a74b5b3f1a3ede0aa6729bfd48e4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 15 Jan 2010 13:42:58 -0800 Subject: iwlwifi: Fix throughput stall issue in HT mode for 5000 Similar to 6000 and 1000 series, RTS/CTS is the recommended protection mechanism for 5000 series in HT mode based on the HW design. Using RTS/CTS will better protect the inner exchange from interference, especially in highly-congested environment, it also prevent uCode encounter TX FIFO underrun and other HT mode related performance issues. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre CC: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 33a5866538e..de45f308b74 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1598,6 +1598,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; @@ -1622,6 +1623,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, }; @@ -1667,6 +1669,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; @@ -1691,6 +1694,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; @@ -1715,6 +1719,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .use_bsm = false, .ht_greenfield_support = true, .led_compensation = 51, + .use_rts_for_ht = true, /* use rts/cts protection */ .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, }; -- cgit v1.2.3 From bb5d2db5709e469f4a8c01eaaee9a275ed9772aa Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 15 Jan 2010 13:42:59 -0800 Subject: iwlwifi: add license to tracing files Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-devtrace.c | 26 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-devtrace.h | 26 ++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index e7d88d1da15..83cc4e500a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -1,3 +1,29 @@ +/****************************************************************************** + * + * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + #include /* sparse doesn't like tracepoint macros */ diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 21361968ab7..d9c7363b1bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -1,3 +1,29 @@ +/****************************************************************************** + * + * Copyright(c) 2009 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) #define __IWLWIFI_DEVICE_TRACE -- cgit v1.2.3 From f5300e04df78feae8107c1846dd3a9e27c071b2f Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Mon, 18 Jan 2010 00:07:38 +0100 Subject: p54pci: rx frame length check A long time ago, a user reported several crashes due to data corruptions which are likely the result of a not-100%-supported, or faulty? PCI bridge. ( http://patchwork.kernel.org/patch/53004/ ) This patch fixes entry #1. "1. p54p_check_rx_ring - skb_over_panic: Under a ping flood or just left running for a bit would panic with a skb_over_panic." As described in the mail: The invalid frame length causes skb_put to bailout and trigger a crash. Note: Simply dropping the frame is problematic, because if its content contains a tx feedback we would lose some portion of the device memory space.... And the driver/mac80211 should handle all other invalid data. Reported-by: Quintin Pitts Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index a15962a19b2..a72f7c2577d 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -197,6 +197,14 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, i %= ring_limit; continue; } + + if (unlikely(len > priv->common.rx_mtu)) { + if (net_ratelimit()) + dev_err(&priv->pdev->dev, "rx'd frame size " + "exceeds length threshold.\n"); + + len = priv->common.rx_mtu; + } skb_put(skb, len); if (p54_rx(dev, skb)) { -- cgit v1.2.3 From ad580db50ee8dccd069ffcd76d6f70fa6d4a62a8 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Mon, 18 Jan 2010 01:24:11 +0000 Subject: zd1211rw: adding 0409:0248 to supported device list Yasuhiro ABE reported success in sourceforge zd1211-dev list. The device is a NEC Aterm WL54GU usb wireless stick. The brand and retail product name NEC, Aterm PA-WL54GU The USB ID's (duh) ID 0409:0248 The chip ID string zd1211rw 1-1:1.0: zd1211b chip 0409:0248 v4810 high 00-1b-8b AL2230S_RF pa0 g--N- The FCC ID unknown Signed-off-by: Hin-Tak Leung Signed-off-by: Yasuhiro ABE Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index ac19ecd19cf..72d3e437e19 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -62,6 +62,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0409, 0x0248), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.3 From 3c9d8eccd8687f0e770e4d89fd0d73d4f81a985a Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Thu, 14 Jan 2010 20:58:05 +0000 Subject: [WATCHDOG] iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs This patch adds the Intel Cougar Point and PCH DeviceIDs for iTCO Watchdog. Signed-off-by: Seth Heasley Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index c8a3bec2683..4bdb7f1a907 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -29,8 +29,9 @@ * document number 313056-003, 313057-017: 82801H (ICH8) * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) - * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) + * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) * document number 320066-003, 320257-008: EP80597 (IICH) + * document number TBD : Cougar Point (CPT) */ /* @@ -100,8 +101,22 @@ enum iTCO_chipsets { TCO_ICH10DO, /* ICH10DO */ TCO_PCH, /* PCH Desktop Full Featured */ TCO_PCHM, /* PCH Mobile Full Featured */ + TCO_P55, /* P55 */ + TCO_PM55, /* PM55 */ + TCO_H55, /* H55 */ + TCO_QM57, /* QM57 */ + TCO_H57, /* H57 */ + TCO_HM55, /* HM55 */ + TCO_Q57, /* Q57 */ + TCO_HM57, /* HM57 */ TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ + TCO_QS57, /* QS57 */ + TCO_3400, /* 3400 */ + TCO_3420, /* 3420 */ + TCO_3450, /* 3450 */ TCO_EP80579, /* EP80579 */ + TCO_CPTD, /* CPT Desktop */ + TCO_CPTM, /* CPT Mobile */ }; static struct { @@ -144,8 +159,22 @@ static struct { {"ICH10DO", 2}, {"PCH Desktop Full Featured", 2}, {"PCH Mobile Full Featured", 2}, + {"P55", 2}, + {"PM55", 2}, + {"H55", 2}, + {"QM57", 2}, + {"H57", 2}, + {"HM55", 2}, + {"Q57", 2}, + {"HM57", 2}, {"PCH Mobile SFF Full Featured", 2}, + {"QS57", 2}, + {"3400", 2}, + {"3420", 2}, + {"3450", 2}, {"EP80579", 2}, + {"CPT Desktop", 2}, + {"CPT Mobile", 2}, {NULL, 0} }; @@ -216,8 +245,22 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, + { ITCO_PCI_DEVICE(0x3b02, TCO_P55)}, + { ITCO_PCI_DEVICE(0x3b03, TCO_PM55)}, + { ITCO_PCI_DEVICE(0x3b06, TCO_H55)}, + { ITCO_PCI_DEVICE(0x3b07, TCO_QM57)}, + { ITCO_PCI_DEVICE(0x3b08, TCO_H57)}, + { ITCO_PCI_DEVICE(0x3b09, TCO_HM55)}, + { ITCO_PCI_DEVICE(0x3b0a, TCO_Q57)}, + { ITCO_PCI_DEVICE(0x3b0b, TCO_HM57)}, { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, + { ITCO_PCI_DEVICE(0x3b0f, TCO_QS57)}, + { ITCO_PCI_DEVICE(0x3b12, TCO_3400)}, + { ITCO_PCI_DEVICE(0x3b14, TCO_3420)}, + { ITCO_PCI_DEVICE(0x3b16, TCO_3450)}, { ITCO_PCI_DEVICE(0x5031, TCO_EP80579)}, + { ITCO_PCI_DEVICE(0x1c42, TCO_CPTD)}, + { ITCO_PCI_DEVICE(0x1c43, TCO_CPTM)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3 From 4f9c85a1b03bfa5c0a0d8488a3a7766f3c9fb756 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 18 Jan 2010 05:37:16 +0000 Subject: phylib: Move workqueue initialization to a proper place commit 541cd3ee00a4fe975b22fac6a3bc846bacef37f7 ("phylib: Fix deadlock on resume") caused TI DaVinci EMAC ethernet driver to oops upon resume: PM: resume of devices complete after 237.098 msecs Restarting tasks ... done. kernel BUG at kernel/workqueue.c:354! Unable to handle kernel NULL pointer dereference at virtual address 00000000 [...] Backtrace: [] (__bug+0x0/0x2c) from [] (queue_delayed_work_on+0x74/0xf8) [] (queue_delayed_work_on+0x0/0xf8) from [] (queue_delayed_work+0x2c/0x30) The oops pops up because TI DaVinci EMAC driver detaches PHY on suspend and attaches it back on resume. Attaching makes phylib call phy_start_machine() that initializes a workqueue. On the other hand, PHY's resume routine will call phy_start_machine() again, and that will cause the oops since we just destroyed the already scheduled workqueue. This patch fixes the issue by moving workqueue initialization to phy_device_create(). p.s. We don't see this oops with ucc_geth and gianfar drivers because they perform a fine-grained suspend, i.e. they just stop the PHYs without detaching. Reported-by: Sekhar Nori Signed-off-by: Anton Vorontsov Tested-by: Sekhar Nori Signed-off-by: David S. Miller --- drivers/net/phy/phy.c | 4 +--- drivers/net/phy/phy_device.c | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b0e9f9c5172..0295097d6c4 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -410,7 +410,6 @@ EXPORT_SYMBOL(phy_start_aneg); static void phy_change(struct work_struct *work); -static void phy_state_machine(struct work_struct *work); /** * phy_start_machine - start PHY state machine tracking @@ -430,7 +429,6 @@ void phy_start_machine(struct phy_device *phydev, { phydev->adjust_state = handler; - INIT_DELAYED_WORK(&phydev->state_queue, phy_state_machine); schedule_delayed_work(&phydev->state_queue, HZ); } @@ -761,7 +759,7 @@ EXPORT_SYMBOL(phy_start); * phy_state_machine - Handle the state machine * @work: work_struct that describes the work to be done */ -static void phy_state_machine(struct work_struct *work) +void phy_state_machine(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct phy_device *phydev = diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8212b2b9342..adbc0fded13 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -177,6 +177,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) dev->state = PHY_DOWN; mutex_init(&dev->lock); + INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); return dev; } -- cgit v1.2.3 From 34692421bc7d6145ef383b014860f4fde10b7505 Mon Sep 17 00:00:00 2001 From: Jiajun Wu Date: Mon, 18 Jan 2010 05:47:50 +0000 Subject: ucc_geth: Fix full TX queue processing commit 7583605b6d29f1f7f6fc505b883328089f3485ad ("ucc_geth: Fix empty TX queue processing") fixed empty TX queue mishandling, but didn't account another corner case: when TX queue becomes full. Without this patch the driver will stop transmiting when TX queue becomes full since 'bd == ugeth->txBd[txQ]' actually checks for two things: queue empty or full. Let's better check for NULL skb, which unambiguously signals an empty queue. Signed-off-by: Jiajun Wu Signed-off-by: Anton Vorontsov Cc: Stable [2.6.32] Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 96bdc0b4388..eb8fe7e16c6 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3279,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) /* Handle the transmitted buffer and release */ /* the BD to be used with the current frame */ - if (bd == ugeth->txBd[txQ]) /* queue empty? */ + skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; + if (!skb) break; dev->stats.tx_packets++; - skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; - if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN && skb_recycle_check(skb, ugeth->ug_info->uf_info.max_rx_buf_length + -- cgit v1.2.3 From 357d46a17e54c9a87e0e6ef3930ff4ab2d232b81 Mon Sep 17 00:00:00 2001 From: Matthew Slattery Date: Mon, 18 Jan 2010 05:47:16 +0000 Subject: sfc: QT202x: Remove unreliable MMD check at initialisation Checking the PHY XS MMD here is unnecessary and can give false negatives. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/qt202x_phy.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index ff8f0a417fa..e0d13a45101 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c @@ -318,12 +318,6 @@ static int qt202x_reset_phy(struct efx_nic *efx) /* Wait 250ms for the PHY to complete bootup */ msleep(250); - /* Check that all the MMDs we expect are present and responding. We - * expect faults on some if the link is down, but not on the PHY XS */ - rc = efx_mdio_check_mmds(efx, QT202X_REQUIRED_DEVS, MDIO_DEVS_PHYXS); - if (rc < 0) - goto fail; - falcon_board(efx)->type->init_phy(efx); return rc; -- cgit v1.2.3 From 98f672ca9978c6e5997dbe905c91a73593148a7e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 18 Jan 2010 21:14:12 +0000 Subject: bfin_mac: use the newer CLKBUFOE bit name via asm/dpmc.h This driver tweaks VR_CTL, so pull in the header for the bit defines. Also switch to the new define name as the old one has gone away. Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/net/bfin_mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 8ffea3990d0..0b23bc4f56c 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -386,8 +387,8 @@ static int mii_probe(struct net_device *dev) u32 sclk, mdc_div; /* Enable PHY output early */ - if (!(bfin_read_VR_CTL() & PHYCLKOE)) - bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE); + if (!(bfin_read_VR_CTL() & CLKBUFOE)) + bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); sclk = get_sclk(); mdc_div = ((sclk / MDC_CLK) / 2) - 1; -- cgit v1.2.3 From 2d146eb172d5f754e3973a3f761f7619ebb12df9 Mon Sep 17 00:00:00 2001 From: Ram Vepa Date: Tue, 19 Jan 2010 12:36:20 -0800 Subject: S2io: two branches the same in wait_for_cmd_complete() Fix check to verify if a register bit is set. We have not hit this bug because wait_for_cmd_complete() is always called with S2IO_BIT_RESET. Reported by Roel Kluin . Signed-off-by: Ram Vepa Signed-off-by: David S. Miller --- drivers/net/s2io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index cc4218667cb..3c4836d0898 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -3421,7 +3421,7 @@ static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit, break; } } else { - if (!(val64 & busy_bit)) { + if (val64 & busy_bit) { ret = SUCCESS; break; } -- cgit v1.2.3 From 2205cbe8ecaf5f3ab911cef839c94d05ea5b0c76 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Tue, 19 Jan 2010 16:55:41 -0700 Subject: ACPI: processor: restrict early _PDC to opt-in platforms Commit 78f1699 (ACPI: processor: call _PDC early) blindly walks the namespace and calls _PDC on every processor object it finds. This change may cause issues on platforms that declare dummy values for SSDTs on non-present processors (disabled in MADT). When we call _PDC and dynamically attempt to execute the AML Load() op on these dummy SSDTs, there's no telling what might happen. Rather than finding every platform that has bogus SSDTs, restrict early _PDC calls to platforms that are known to need early evaluation of _PDC. This is a minimal, temporary fix (given the context of the current release cycle). A real solution of checking the MADT for non-present processors will be written for the next merge window. References: http://bugzilla.kernel.org/show_bug.cgi?id=14710 http://bugzilla.kernel.org/show_bug.cgi?id=14954 Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf3..f3364371207 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle) } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); +static int early_pdc_optin; +static int set_early_pdc_optin(const struct dmi_system_id *id) +{ + early_pdc_optin = 1; + return 0; +} + +static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { + { + set_early_pdc_optin, "HP Envy", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv6", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv7", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, + {}, +}; + static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { @@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void) */ dmi_check_system(processor_idle_dmi_table); + /* + * Allow systems to opt-in to early _PDC evaluation. + */ + dmi_check_system(early_pdc_optin_table); + if (!early_pdc_optin) + return; + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); -- cgit v1.2.3 From 7f07a605a3929d2d94dcbad8ccb7d280958d21f9 Mon Sep 17 00:00:00 2001 From: Darren Jenkins Date: Tue, 12 Jan 2010 23:37:07 +1100 Subject: ACPI: power_meter: remove double kfree() resource->domain_devices can be double kfree()'d in a couple of places. Fix this by setting num_domain_devices = 0 after the kfree(). Coverity CID: 13356, 13355, 13354 Signed-off-by: Darren Jenkins Acked-by: Darrick J. Wong Signed-off-by: Len Brown --- drivers/acpi/power_meter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index ca75c36f754..dc4ffadf812 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c @@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) kfree(resource->domain_devices); kobject_put(resource->holders_dir); + resource->num_domain_devices = 0; } static int read_domain_devices(struct acpi_power_meter_resource *resource) @@ -740,7 +741,6 @@ skip_unsafe_cap: return res; error: - remove_domain_devices(resource); remove_attrs(resource); return res; } -- cgit v1.2.3 From 5d76b6f6c17572e662f5c99c2023adae92100855 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 22:41:14 -0500 Subject: ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C Linux has always ignored ACPI BIOS C2 with exit latency > 100 usec, and the ACPI spec is clear that is correct FADT-supplied C2. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 100usec C2 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. This bug has not been visible until Nehalem, which advertises a CPU-C2 worst case exit latency on servers of 205usec. That (incorrect) figure is being used by BIOS writers on mobile Nehalem systems for the AC configuration. Thus, Linux ignores C2 leaving just C1, which is saves less power, and also impacts performance by preventing the use of turbo mode. http://bugzilla.kernel.org/show_bug.cgi?id=15064 Tested-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d1676b1754d..8f6da9acc8e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -305,6 +305,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; + /* + * FADT specified C2 latency must be less than or equal to + * 100 microseconds. + */ + if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); + /* invalidate C2 */ + pr->power.states[ACPI_STATE_C2].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -500,16 +511,6 @@ static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) if (!cx->address) return; - /* - * C2 latency must be less than or equal to 100 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * Otherwise we've met all of our C2 requirements. * Normalize the C2 latency to expidite policy -- cgit v1.2.3 From a6d72c189f6c4292ba1a323e8af24083790529f8 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 23:10:04 -0500 Subject: ACPI: allow C3 > 1000usec Do for C3 what the previous patch did for C2. The C2 patch was in response to a highly visible and multiply reported C-state/turbo failure, while this change has no bug report in-hand. This will enable C3 in Linux on systems where BIOS overstates C3 latency in _CST. It will also enable future systems which may actually have C3 > 1000usec. Linux has always ignored ACPI BIOS C3 with exit latency > 1000 usec, and the ACPI spec is clear that is correct FADT-supplied C3. However, the ACPI spec explicitly states that _CST-supplied C-states have no latency limits. So move the 1000usec C3 test out of the code shared by FADT and _CST code-paths, and into the FADT-specific path. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 8f6da9acc8e..2c543b42eb1 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -316,6 +316,17 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].address = 0; } + /* + * FADT supplied C3 latency must be less than or equal to + * 1000 microseconds. + */ + if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); + /* invalidate C3 */ + pr->power.states[ACPI_STATE_C3].address = 0; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -532,16 +543,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, if (!cx->address) return; - /* - * C3 latency must be less than or equal to 1000 - * microseconds. - */ - else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "latency too large [%d]\n", cx->latency)); - return; - } - /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. -- cgit v1.2.3 From d22edd293ff3f1e2d252f164fe2cf744620cb660 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 19 Jan 2010 23:29:09 -0500 Subject: ACPI: delete acpi_processor_power_verify_c2() no functional change -- cleanup only. acpi_processor_power_verify_c2() was nearly empty due to a previous patch, so expand its remains into its one caller and delete it. Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2c543b42eb1..7c0441f63b3 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -516,23 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) return status; } -static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) -{ - - if (!cx->address) - return; - - /* - * Otherwise we've met all of our C2 requirements. - * Normalize the C2 latency to expidite policy - */ - cx->valid = 1; - - cx->latency_ticks = cx->latency; - - return; -} - static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx) { @@ -631,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) break; case ACPI_STATE_C2: - acpi_processor_power_verify_c2(cx); + if (!cx->address) + break; + cx->valid = 1; + cx->latency_ticks = cx->latency; /* Normalize latency */ break; case ACPI_STATE_C3: -- cgit v1.2.3 From 534ead709235b967b659947c55d9130873a432c4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 14 Jan 2010 16:18:09 +0900 Subject: libata: retry FS IOs even if it has failed with AC_ERR_INVALID libata currently doesn't retry if a command fails with AC_ERR_INVALID assuming that retrying won't get it any further even if retried. However, a failure may be classified as invalid through hardware glitch (incorrect reading of the error register or firmware bug) and there isn't whole lot to gain by not retrying as actually invalid commands will be failed immediately. Also, commands serving FS IOs are extremely unlikely to be invalid. Retry FS IOs even if it's marked invalid. Transient and incorrect invalid failure was seen while debugging firmware related issue on Samsung n130 on bko#14314. http://bugzilla.kernel.org/show_bug.cgi?id=14314 Signed-off-by: Tejun Heo Reported-by: Johannes Stezenbach Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 0ea97c942ce..9f6cfac0f2c 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2028,8 +2028,9 @@ static void ata_eh_link_autopsy(struct ata_link *link) qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); /* determine whether the command is worth retrying */ - if (!(qc->err_mask & AC_ERR_INVALID) && - ((qc->flags & ATA_QCFLAG_IO) || qc->err_mask != AC_ERR_DEV)) + if (qc->flags & ATA_QCFLAG_IO || + (!(qc->err_mask & AC_ERR_INVALID) && + qc->err_mask != AC_ERR_DEV)) qc->flags |= ATA_QCFLAG_RETRY; /* accumulate error info */ -- cgit v1.2.3 From f776c5ec4690b21b3668ad5956774a22c86f541a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 18 Jan 2010 14:36:12 +0100 Subject: driver-core: fix devtmpfs crash on s390 On Mon, Jan 18, 2010 at 05:26:20PM +0530, Sachin Sant wrote: > Hello Heiko, > > Today while trying to boot next-20100118 i came across > the following Oops : > > Brought up 4 CPUs > Unable to handle kernel pointer dereference at virtual kernel address 0000000000 > 543000 > Oops: 0004 #1 SMP > Modules linked in: > CPU: 0 Not tainted 2.6.33-rc4-autotest-next-20100118-5-default #1 > Process swapper (pid: 1, task: 00000000fd792038, ksp: 00000000fd797a30) > Krnl PSW : 0704200180000000 00000000001eb0b8 (shmem_parse_options+0xc0/0x328) > R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:2 PM:0 EA:3 > Krnl GPRS: 000000000054388a 000000000000003d 0000000000543836 000000000000003d > 0000000000000000 0000000000483f28 0000000000536112 00000000fd797d00 > 00000000fd4ba100 0000000000000100 0000000000483978 0000000000543832 > 0000000000000000 0000000000465958 00000000001eb0b0 00000000fd797c58 > Krnl Code: 00000000001eb0aa: c0e5000994f1 brasl %r14,31da8c > 00000000001eb0b0: b9020022 ltgr %r2,%r2 > 00000000001eb0b4: a784010b brc 8,1eb2ca > >00000000001eb0b8: 92002000 mvi 0(%r2),0 > 00000000001eb0bc: a7080000 lhi %r0,0 > 00000000001eb0c0: 41902001 la %r9,1(%r2) > 00000000001eb0c4: b9040016 lgr %r1,%r6 > 00000000001eb0c8: b904002b lgr %r2,%r11 > Call Trace: > (<00000000fd797c50> 0xfd797c50) > <00000000001eb5da> shmem_fill_super+0x13a/0x25c > <0000000000228cfa> get_sb_single+0xbe/0xdc > <000000000034ffc0> dev_get_sb+0x2c/0x38 > <000000000066c602> devtmpfs_init+0x46/0xc0 > <000000000066c53e> driver_init+0x22/0x60 > <000000000064d40a> kernel_init+0x24e/0x3d0 > <000000000010a7ea> kernel_thread_starter+0x6/0xc > <000000000010a7e4> kernel_thread_starter+0x0/0xc > > I never tried to boot a kernel with DEVTMPFS enabled on a s390 box. > So am wondering if this is supported or not ? If you think this > is supported i will send a mail to community on this. There is nothing arch specific to devtmpfs. This part crashes because the kernel tries to modify the data read-only section which is write protected on s390. Signed-off-by: Heiko Carstens Acked-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 090dd485130..42ae452b36b 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -354,6 +354,7 @@ int __init devtmpfs_init(void) { int err; struct vfsmount *mnt; + char options[] = "mode=0755"; err = register_filesystem(&dev_fs_type); if (err) { @@ -362,7 +363,7 @@ int __init devtmpfs_init(void) return err; } - mnt = kern_mount_data(&dev_fs_type, "mode=0755"); + mnt = kern_mount_data(&dev_fs_type, options); if (IS_ERR(mnt)) { err = PTR_ERR(mnt); printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); -- cgit v1.2.3 From bd796671f093d5b1841d383674d5650f5ec6c9c6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jan 2010 13:08:16 -0800 Subject: Revert "sysdev: fix prototype for memory_sysdev_class show/store functions" This reverts commit 8ff410daa009c4b44be445ded5b0cec00abc0426 It should not have been sent to Linus's tree yet, as it depends on changes that are queued up in my driver-core for the .34 kernel merge. Cc: Wu Fengguang Cc: Andi Kleen Cc: "Zheng, Shaohui" Cc: Andrew Morton Cc: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- drivers/base/memory.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index ae6b6c43cff..bd025059711 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -309,19 +309,17 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); * Block size attribute stuff */ static ssize_t -print_block_size(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - char *buf) +print_block_size(struct class *class, char *buf) { return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE); } -static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); +static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL); static int block_size_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_block_size_bytes.attr); + &class_attr_block_size_bytes.attr); } /* @@ -332,9 +330,7 @@ static int block_size_init(void) */ #ifdef CONFIG_ARCH_MEMORY_PROBE static ssize_t -memory_probe_store(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - const char *buf, size_t count) +memory_probe_store(struct class *class, const char *buf, size_t count) { u64 phys_addr; int nid; @@ -350,12 +346,12 @@ memory_probe_store(struct sysdev_class *class, return count; } -static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); +static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { return sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_probe.attr); + &class_attr_probe.attr); } #else static inline int memory_probe_init(void) @@ -371,9 +367,7 @@ static inline int memory_probe_init(void) /* Soft offline a page */ static ssize_t -store_soft_offline_page(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - const char *buf, size_t count) +store_soft_offline_page(struct class *class, const char *buf, size_t count) { int ret; u64 pfn; @@ -390,9 +384,7 @@ store_soft_offline_page(struct sysdev_class *class, /* Forcibly offline a page, including killing processes. */ static ssize_t -store_hard_offline_page(struct sysdev_class *class, - struct sysdev_class_attribute *class_attr, - const char *buf, size_t count) +store_hard_offline_page(struct class *class, const char *buf, size_t count) { int ret; u64 pfn; @@ -405,18 +397,18 @@ store_hard_offline_page(struct sysdev_class *class, return ret ? ret : count; } -static SYSDEV_CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); -static SYSDEV_CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); +static CLASS_ATTR(soft_offline_page, 0644, NULL, store_soft_offline_page); +static CLASS_ATTR(hard_offline_page, 0644, NULL, store_hard_offline_page); static __init int memory_fail_init(void) { int err; err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_soft_offline_page.attr); + &class_attr_soft_offline_page.attr); if (!err) err = sysfs_create_file(&memory_sysdev_class.kset.kobj, - &attr_hard_offline_page.attr); + &class_attr_hard_offline_page.attr); return err; } #else -- cgit v1.2.3 From eeec32a731631a9bad9abb21c626b9f2840bee0d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:26:50 +0000 Subject: nozomi: quick fix for the close/close bug Nozomi goes wrong if you get the sequence open open close [stuff] close which turns out to occur on some ppp type setups. This is a quick patch up for the problem. It's not really fixing Nozomi which completely fails to implement tty open/close semantics and all the other needed stuff. Doing it right is a rather more invasive patch set and not one that will backport. Signed-off-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/char/nozomi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 7d73cd43034..2ad7d37afbd 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -1651,10 +1651,10 @@ static void ntty_close(struct tty_struct *tty, struct file *file) dc->open_ttys--; port->count--; - tty_port_tty_set(port, NULL); if (port->count == 0) { DBG1("close: %d", nport->token_dl); + tty_port_tty_set(port, NULL); spin_lock_irqsave(&dc->spin_mutex, flags); dc->last_ier &= ~(nport->token_dl); writew(dc->last_ier, dc->reg_ier); -- cgit v1.2.3 From 6d34855d9aa281f72c533ecb827405139d1b0fe9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 9 Dec 2009 12:31:37 -0800 Subject: serial: 8250_pnp: use wildcard for serial Wacom tablets Wacom claims that the WACF namespace will always be devoted to serial Wacom tablets. Remove the existing entries and add a wildcard to avoid having to update the kernel every time they add a new device. Signed-off-by: Ping Cheng Signed-off-by: Matthew Garrett Tested-by: Ping Cheng Cc: Alan Cox Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/serial/8250_pnp.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c index b5496a19d96..24485cc62ff 100644 --- a/drivers/serial/8250_pnp.c +++ b/drivers/serial/8250_pnp.c @@ -328,15 +328,7 @@ static const struct pnp_device_id pnp_dev_table[] = { /* U.S. Robotics 56K Voice INT PnP*/ { "USR9190", 0 }, /* Wacom tablets */ - { "WACF004", 0 }, - { "WACF005", 0 }, - { "WACF006", 0 }, - { "WACF007", 0 }, - { "WACF008", 0 }, - { "WACF009", 0 }, - { "WACF00A", 0 }, - { "WACF00B", 0 }, - { "WACF00C", 0 }, + { "WACFXXX", 0 }, /* Compaq touchscreen */ { "FPI2002", 0 }, /* Fujitsu Stylistic touchscreens */ -- cgit v1.2.3 From 4547be7809a3b775ce750ec7f8b5748954741523 Mon Sep 17 00:00:00 2001 From: Stanislav Brabec Date: Wed, 2 Dec 2009 16:20:56 +0100 Subject: serial-core: resume serial hardware with no_console_suspend Perform a tricky suspend/resume even with no_console_suspend. With no_console_suspend, kernel skips serial port suspend/resume and the serial hardware may remain in undefined state after resume. It actually happens on devices that don't have BIOS that handle serial initialization. It makes impossible to use serial console after resume. Devices affected by this problem include: Sharp Zaurus devices Several PXA based ARM embedded boards The patch does: - Save the hardware state - Perform buffer flush in time of its suspend call - Tell the driver that port is suspended - But still accept new data - And keep console hardware in state that allows to send them It allows to capture late console messages without breaking console after resume. This is just a resend of a patch discussed in these threads, as the patch was not yet applied. "Possible suspend/resume regression in .32-rc?" (Nov 1-5, 2009, ARM list, later LKML) "serial-core: resume serial hardware with no_console_suspend" (Sep 15-Oct 18, 2009, LKML & ARM lists) Signed-off-by: Stanislav Brabec Tested-by: Haojian Zhuang Tested-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 88 +++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 047530b285b..fa4f170f2e8 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -2006,12 +2006,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_lock(&port->mutex); - if (!console_suspend_enabled && uart_console(uport)) { - /* we're going to avoid suspending serial console */ - mutex_unlock(&port->mutex); - return 0; - } - tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (device_may_wakeup(tty_dev)) { enable_irq_wake(uport->irq); @@ -2019,20 +2013,23 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_unlock(&port->mutex); return 0; } - uport->suspended = 1; + if (console_suspend_enabled || !uart_console(uport)) + uport->suspended = 1; if (port->flags & ASYNC_INITIALIZED) { const struct uart_ops *ops = uport->ops; int tries; - set_bit(ASYNCB_SUSPENDED, &port->flags); - clear_bit(ASYNCB_INITIALIZED, &port->flags); + if (console_suspend_enabled || !uart_console(uport)) { + set_bit(ASYNCB_SUSPENDED, &port->flags); + clear_bit(ASYNCB_INITIALIZED, &port->flags); - spin_lock_irq(&uport->lock); - ops->stop_tx(uport); - ops->set_mctrl(uport, 0); - ops->stop_rx(uport); - spin_unlock_irq(&uport->lock); + spin_lock_irq(&uport->lock); + ops->stop_tx(uport); + ops->set_mctrl(uport, 0); + ops->stop_rx(uport); + spin_unlock_irq(&uport->lock); + } /* * Wait for the transmitter to empty. @@ -2047,16 +2044,18 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) drv->dev_name, drv->tty_driver->name_base + uport->line); - ops->shutdown(uport); + if (console_suspend_enabled || !uart_console(uport)) + ops->shutdown(uport); } /* * Disable the console device before suspending. */ - if (uart_console(uport)) + if (console_suspend_enabled && uart_console(uport)) console_stop(uport->cons); - uart_change_pm(state, 3); + if (console_suspend_enabled || !uart_console(uport)) + uart_change_pm(state, 3); mutex_unlock(&port->mutex); @@ -2073,29 +2072,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) mutex_lock(&port->mutex); - if (!console_suspend_enabled && uart_console(uport)) { - /* no need to resume serial console, it wasn't suspended */ - /* - * First try to use the console cflag setting. - */ - memset(&termios, 0, sizeof(struct ktermios)); - termios.c_cflag = uport->cons->cflag; - /* - * If that's unset, use the tty termios setting. - */ - if (termios.c_cflag == 0) - termios = *state->port.tty->termios; - else { - termios.c_ispeed = termios.c_ospeed = - tty_termios_input_baud_rate(&termios); - termios.c_ispeed = termios.c_ospeed = - tty_termios_baud_rate(&termios); - } - uport->ops->set_termios(uport, &termios, NULL); - mutex_unlock(&port->mutex); - return 0; - } - tty_dev = device_find_child(uport->dev, &match, serial_match_port); if (!uport->suspended && device_may_wakeup(tty_dev)) { disable_irq_wake(uport->irq); @@ -2121,21 +2097,23 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) spin_lock_irq(&uport->lock); ops->set_mctrl(uport, 0); spin_unlock_irq(&uport->lock); - ret = ops->startup(uport); - if (ret == 0) { - uart_change_speed(state, NULL); - spin_lock_irq(&uport->lock); - ops->set_mctrl(uport, uport->mctrl); - ops->start_tx(uport); - spin_unlock_irq(&uport->lock); - set_bit(ASYNCB_INITIALIZED, &port->flags); - } else { - /* - * Failed to resume - maybe hardware went away? - * Clear the "initialized" flag so we won't try - * to call the low level drivers shutdown method. - */ - uart_shutdown(state); + if (console_suspend_enabled || !uart_console(uport)) { + ret = ops->startup(uport); + if (ret == 0) { + uart_change_speed(state, NULL); + spin_lock_irq(&uport->lock); + ops->set_mctrl(uport, uport->mctrl); + ops->start_tx(uport); + spin_unlock_irq(&uport->lock); + set_bit(ASYNCB_INITIALIZED, &port->flags); + } else { + /* + * Failed to resume - maybe hardware went away? + * Clear the "initialized" flag so we won't try + * to call the low level drivers shutdown method. + */ + uart_shutdown(state); + } } clear_bit(ASYNCB_SUSPENDED, &port->flags); -- cgit v1.2.3 From 16ae2a877bf4179737921235e85ceffd7b79354f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 4 Jan 2010 16:26:21 +0000 Subject: serial: Fix crash if the minimum rate of the device is > 9600 baud In that situation if the old rate is invalid and the new rate is invalid and the chip cannot do 9600 baud we report zero, which makes all the drivers explode. Instead force the rate based on min/max Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_core.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index fa4f170f2e8..7f283070951 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -385,13 +385,20 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, } /* - * As a last resort, if the quotient is zero, - * default to 9600 bps + * As a last resort, if the range cannot be met then clip to + * the nearest chip supported rate. */ - if (!hung_up) - tty_termios_encode_baud_rate(termios, 9600, 9600); + if (!hung_up) { + if (baud <= min) + tty_termios_encode_baud_rate(termios, + min + 1, min + 1); + else + tty_termios_encode_baud_rate(termios, + max - 1, max - 1); + } } - + /* Should never happen */ + WARN_ON(1); return 0; } -- cgit v1.2.3 From 2e2eb509aa7a333fe9931cf306fc7dbc3473f25b Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 9 Dec 2009 12:31:36 -0800 Subject: serial: imx: bit &/| confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since UCR1_UARTEN is defined 1, the port was always treated as enabled. Signed-off-by: Roel Kluin Cc: Alan Cox Acked-by: Oskar Schirmer Cc: Sascha Hauer Cc: Fabian Godehardt Cc: Daniel Glöckner Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/imx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 18130f11238..60d665a17a8 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -1088,7 +1088,7 @@ imx_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { - if ( readl(sport->port.membase + UCR1) | UCR1_UARTEN ) { + if (readl(sport->port.membase + UCR1) & UCR1_UARTEN) { /* ok, the port was enabled */ unsigned int ucr2, ubir,ubmr, uartclk; unsigned int baud_raw; -- cgit v1.2.3 From 18c576f950167ff3ec1e56dcbbec7b87288b3237 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 9 Dec 2009 12:31:31 -0800 Subject: serial: serial_cs: oxsemi quirk breaks resume Quirk is applied on all cards with given manfid (is it that correct?). Unfortunately, that quirk breaks resume on zaurus with billionton bluetooth card inserted: c950ctrl is 0 and outb() faults. I believe it is simply not a multiport card. (info->multi == 1). ... ... confirmed by printks. Signed-off-by: Pavel Machek Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/serial/serial_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 0ee7239c5d6..df854401af2 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -146,7 +146,8 @@ static void quirk_wakeup_oxsemi(struct pcmcia_device *link) { struct serial_info *info = link->priv; - outb(12, info->c950ctrl + 1); + if (info->c950ctrl) + outb(12, info->c950ctrl + 1); } /* request_region? oxsemi branch does no request_region too... */ -- cgit v1.2.3 From 703625118069f9f8960d356676662d3db5a9d116 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Dec 2009 07:07:19 -0800 Subject: tty: fix race in tty_fasync We need to keep the lock held over the call to __f_setown() to prevent a PID race. Thanks to Al Viro for pointing out the problem, and to Travis for making us look here in the first place. Cc: Eric W. Biederman Cc: Al Viro Cc: Alan Cox Cc: Linus Torvalds Cc: Tavis Ormandy Cc: Jeff Dike Cc: Julien Tinnes Cc: Matt Mackall Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f15df40bc31..c6f3b48be9d 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1951,8 +1951,8 @@ static int tty_fasync(int fd, struct file *filp, int on) pid = task_pid(current); type = PIDTYPE_PID; } - spin_unlock_irqrestore(&tty->ctrl_lock, flags); retval = __f_setown(filp, pid, type, 0); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (retval) goto out; } else { -- cgit v1.2.3 From 20633bf0141c5e93e3396770d5eb7d200ee4068a Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Wed, 23 Dec 2009 10:27:22 -0200 Subject: Staging: asus_oled: fix oops in 2.6.32.2 After updating to 2.6.32 kernel, I started experiencing Oopses caused by the asus_oled module. After quick investigation, I wrapped this simple patch which fixes an Oops in by asus_oled module on 2.6.32.2 kernel, caused by incorrect usage of strict_strtoul function call within set_enabled and set_disabled functions. This can be triggered by simple running the userspace client for asus_old (e.g., 'asusoled -e' or 'asusoled -d'). Signed-off-by: Eugeni Dodonov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/asus_oled/asus_oled.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c index f4c26572c7d..43c57b7688a 100644 --- a/drivers/staging/asus_oled/asus_oled.c +++ b/drivers/staging/asus_oled/asus_oled.c @@ -194,9 +194,11 @@ static ssize_t set_enabled(struct device *dev, struct device_attribute *attr, { struct usb_interface *intf = to_usb_interface(dev); struct asus_oled_dev *odev = usb_get_intfdata(intf); - int temp = strict_strtoul(buf, 10, NULL); + unsigned long value; + if (strict_strtoul(buf, 10, &value)) + return -EINVAL; - enable_oled(odev, temp); + enable_oled(odev, value); return count; } @@ -207,10 +209,12 @@ static ssize_t class_set_enabled(struct device *device, { struct asus_oled_dev *odev = (struct asus_oled_dev *) dev_get_drvdata(device); + unsigned long value; - int temp = strict_strtoul(buf, 10, NULL); + if (strict_strtoul(buf, 10, &value)) + return -EINVAL; - enable_oled(odev, temp); + enable_oled(odev, value); return count; } -- cgit v1.2.3 From d31a2ff03f31cbecb92bdc5b1ab9d62fb70971d7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 6 Jan 2010 14:01:26 +0000 Subject: Staging: et131x: Fix 2.6.33rc1 regression in et131x et131x: Fix 12bit wrapping From: Alan Cox The 12bit wrap logic conversion is wrong and this shows up for some memory sizes and layouts of card. Patch it up for now, once the kernel view of status is cleaned up it'll become two variables and a lot saner. Signed-off-by: Alan Cox Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et1310_address_map.h | 18 +++++++++++++----- drivers/staging/et131x/et1310_rx.c | 6 +++--- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h index 6da843cc343..e715e4dcb52 100644 --- a/drivers/staging/et131x/et1310_address_map.h +++ b/drivers/staging/et131x/et1310_address_map.h @@ -203,11 +203,14 @@ typedef struct _GLOBAL_t { /* Location: */ * 9-0: pr ndes */ -#define ET_DMA10_MASK 0x3FF /* 10 bit mask for DMA10W types */ -#define ET_DMA10_WRAP 0x400 -#define ET_DMA4_MASK 0x00F /* 4 bit mask for DMA4W types */ -#define ET_DMA4_WRAP 0x010 - +#define ET_DMA12_MASK 0x0FFF /* 12 bit mask for DMA12W types */ +#define ET_DMA12_WRAP 0x1000 +#define ET_DMA10_MASK 0x03FF /* 10 bit mask for DMA10W types */ +#define ET_DMA10_WRAP 0x0400 +#define ET_DMA4_MASK 0x000F /* 4 bit mask for DMA4W types */ +#define ET_DMA4_WRAP 0x0010 + +#define INDEX12(x) ((x) & ET_DMA12_MASK) #define INDEX10(x) ((x) & ET_DMA10_MASK) #define INDEX4(x) ((x) & ET_DMA4_MASK) @@ -216,6 +219,11 @@ extern inline void add_10bit(u32 *v, int n) *v = INDEX10(*v + n) | (*v & ET_DMA10_WRAP); } +extern inline void add_12bit(u32 *v, int n) +{ + *v = INDEX12(*v + n) | (*v & ET_DMA12_WRAP); +} + /* * 10bit DMA with wrap * txdma tx queue write address reg in txdma address map at 0x1010 diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c index 3ddc9b12b8d..81c1a7478ad 100644 --- a/drivers/staging/et131x/et1310_rx.c +++ b/drivers/staging/et131x/et1310_rx.c @@ -831,10 +831,10 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev) /* Indicate that we have used this PSR entry. */ /* FIXME wrap 12 */ - rx_local->local_psr_full = (rx_local->local_psr_full + 1) & 0xFFF; - if (rx_local->local_psr_full > rx_local->PsrNumEntries - 1) { + add_12bit(&rx_local->local_psr_full, 1); + if ((rx_local->local_psr_full & 0xFFF) > rx_local->PsrNumEntries - 1) { /* Clear psr full and toggle the wrap bit */ - rx_local->local_psr_full &= 0xFFF; + rx_local->local_psr_full &= ~0xFFF; rx_local->local_psr_full ^= 0x1000; } -- cgit v1.2.3 From 7692fd4d441afac728cb83fdd33349d5ba07406c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 Jan 2010 09:06:40 -0800 Subject: Staging: hv: fix smp problems in the hyperv core code This fixes a number of SMP problems that were in the hyperv core code. Patch originally written by K. Y. Srinivasan but forward ported to the latest in-kernel code and tweaked slightly by me. Novell, Inc. hereby disclaims all copyright in any derivative work copyright associated with this patch. Signed-off-by: K. Y. Srinivasan Cc: Hank Janssen Cc: Haiyang Zhang . Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hv/Hv.c | 50 +++++++++++++++++++++++----------------------- drivers/staging/hv/Hv.h | 6 +++--- drivers/staging/hv/Vmbus.c | 12 ++++++----- 3 files changed, 35 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c index c5b6613f2f2..c2809f2a2ce 100644 --- a/drivers/staging/hv/Hv.c +++ b/drivers/staging/hv/Hv.c @@ -386,7 +386,7 @@ u16 HvSignalEvent(void) * retrieve the initialized message and event pages. Otherwise, we create and * initialize the message and event pages. */ -int HvSynicInit(u32 irqVector) +void HvSynicInit(void *irqarg) { u64 version; union hv_synic_simp simp; @@ -394,13 +394,14 @@ int HvSynicInit(u32 irqVector) union hv_synic_sint sharedSint; union hv_synic_scontrol sctrl; u64 guestID; - int ret = 0; + u32 irqVector = *((u32 *)(irqarg)); + int cpu = smp_processor_id(); DPRINT_ENTER(VMBUS); if (!gHvContext.HypercallPage) { DPRINT_EXIT(VMBUS); - return ret; + return; } /* Check the version */ @@ -425,27 +426,27 @@ int HvSynicInit(u32 irqVector) */ rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID); if (guestID == HV_LINUX_GUEST_ID) { - gHvContext.synICMessagePage[0] = + gHvContext.synICMessagePage[cpu] = phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT); - gHvContext.synICEventPage[0] = + gHvContext.synICEventPage[cpu] = phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT); } else { DPRINT_ERR(VMBUS, "unknown guest id!!"); goto Cleanup; } DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p", - gHvContext.synICMessagePage[0], - gHvContext.synICEventPage[0]); + gHvContext.synICMessagePage[cpu], + gHvContext.synICEventPage[cpu]); } else { - gHvContext.synICMessagePage[0] = osd_PageAlloc(1); - if (gHvContext.synICMessagePage[0] == NULL) { + gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); + if (gHvContext.synICMessagePage[cpu] == NULL) { DPRINT_ERR(VMBUS, "unable to allocate SYNIC message page!!"); goto Cleanup; } - gHvContext.synICEventPage[0] = osd_PageAlloc(1); - if (gHvContext.synICEventPage[0] == NULL) { + gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC); + if (gHvContext.synICEventPage[cpu] == NULL) { DPRINT_ERR(VMBUS, "unable to allocate SYNIC event page!!"); goto Cleanup; @@ -454,7 +455,7 @@ int HvSynicInit(u32 irqVector) /* Setup the Synic's message page */ rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64); simp.SimpEnabled = 1; - simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[0]) + simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu]) >> PAGE_SHIFT; DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", @@ -465,7 +466,7 @@ int HvSynicInit(u32 irqVector) /* Setup the Synic's event page */ rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); siefp.SiefpEnabled = 1; - siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[0]) + siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu]) >> PAGE_SHIFT; DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", @@ -501,32 +502,30 @@ int HvSynicInit(u32 irqVector) DPRINT_EXIT(VMBUS); - return ret; + return; Cleanup: - ret = -1; - if (gHvContext.GuestId == HV_LINUX_GUEST_ID) { - if (gHvContext.synICEventPage[0]) - osd_PageFree(gHvContext.synICEventPage[0], 1); + if (gHvContext.synICEventPage[cpu]) + osd_PageFree(gHvContext.synICEventPage[cpu], 1); - if (gHvContext.synICMessagePage[0]) - osd_PageFree(gHvContext.synICMessagePage[0], 1); + if (gHvContext.synICMessagePage[cpu]) + osd_PageFree(gHvContext.synICMessagePage[cpu], 1); } DPRINT_EXIT(VMBUS); - - return ret; + return; } /** * HvSynicCleanup - Cleanup routine for HvSynicInit(). */ -void HvSynicCleanup(void) +void HvSynicCleanup(void *arg) { union hv_synic_sint sharedSint; union hv_synic_simp simp; union hv_synic_siefp siefp; + int cpu = smp_processor_id(); DPRINT_ENTER(VMBUS); @@ -539,6 +538,7 @@ void HvSynicCleanup(void) sharedSint.Masked = 1; + /* Need to correctly cleanup in the case of SMP!!! */ /* Disable the interrupt */ wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64); @@ -560,8 +560,8 @@ void HvSynicCleanup(void) wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64); - osd_PageFree(gHvContext.synICMessagePage[0], 1); - osd_PageFree(gHvContext.synICEventPage[0], 1); + osd_PageFree(gHvContext.synICMessagePage[cpu], 1); + osd_PageFree(gHvContext.synICEventPage[cpu], 1); } DPRINT_EXIT(VMBUS); diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h index 5379e4bfc56..fce4b5cdac3 100644 --- a/drivers/staging/hv/Hv.h +++ b/drivers/staging/hv/Hv.h @@ -93,7 +93,7 @@ static const struct hv_guid VMBUS_SERVICE_ID = { }, }; -#define MAX_NUM_CPUS 1 +#define MAX_NUM_CPUS 32 struct hv_input_signal_event_buffer { @@ -137,8 +137,8 @@ extern u16 HvPostMessage(union hv_connection_id connectionId, extern u16 HvSignalEvent(void); -extern int HvSynicInit(u32 irqVector); +extern void HvSynicInit(void *irqarg); -extern void HvSynicCleanup(void); +extern void HvSynicCleanup(void *arg); #endif /* __HV_H__ */ diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c index a4dd06f6d45..35a023e9f9d 100644 --- a/drivers/staging/hv/Vmbus.c +++ b/drivers/staging/hv/Vmbus.c @@ -129,7 +129,7 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo) /* strcpy(dev->name, "vmbus"); */ /* SynIC setup... */ - ret = HvSynicInit(*irqvector); + on_each_cpu(HvSynicInit, (void *)irqvector, 1); /* Connect to VMBus in the root partition */ ret = VmbusConnect(); @@ -150,7 +150,7 @@ static int VmbusOnDeviceRemove(struct hv_device *dev) DPRINT_ENTER(VMBUS); VmbusChannelReleaseUnattachedChannels(); VmbusDisconnect(); - HvSynicCleanup(); + on_each_cpu(HvSynicCleanup, NULL, 1); DPRINT_EXIT(VMBUS); return ret; @@ -173,7 +173,8 @@ static void VmbusOnCleanup(struct hv_driver *drv) */ static void VmbusOnMsgDPC(struct hv_driver *drv) { - void *page_addr = gHvContext.synICMessagePage[0]; + int cpu = smp_processor_id(); + void *page_addr = gHvContext.synICMessagePage[cpu]; struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; struct hv_message *copied; @@ -230,11 +231,12 @@ static void VmbusOnEventDPC(struct hv_driver *drv) static int VmbusOnISR(struct hv_driver *drv) { int ret = 0; + int cpu = smp_processor_id(); void *page_addr; struct hv_message *msg; union hv_synic_event_flags *event; - page_addr = gHvContext.synICMessagePage[0]; + page_addr = gHvContext.synICMessagePage[cpu]; msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; DPRINT_ENTER(VMBUS); @@ -248,7 +250,7 @@ static int VmbusOnISR(struct hv_driver *drv) } /* TODO: Check if there are events to be process */ - page_addr = gHvContext.synICEventPage[0]; + page_addr = gHvContext.synICEventPage[cpu]; event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; /* Since we are a child, we only need to check bit 0 */ -- cgit v1.2.3 From 25719e6b4631959c9ecb1db6967537a124c4a7fa Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Tue, 5 Jan 2010 14:30:31 +0100 Subject: USB: serial: fix USB serial fix kfifo_len locking This patch fix a possible race bug in drivers/usb/serial/generic with the new kfifo API. Please apply it to the 2.6.33-rc* tree. Signed-off-by: Stefani Seibold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f1ea3a33b6e..5ce033ab9b9 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -386,12 +386,12 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) dbg("%s - port %d", __func__, port->number); - if (serial->type->max_in_flight_urbs) { - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&port->lock, flags); + if (serial->type->max_in_flight_urbs) chars = port->tx_bytes_flight; - spin_unlock_irqrestore(&port->lock, flags); - } else if (serial->num_bulk_out) + else if (serial->num_bulk_out) chars = kfifo_len(&port->write_fifo); + spin_unlock_irqrestore(&port->lock, flags); dbg("%s - returns %d", __func__, chars); return chars; -- cgit v1.2.3 From 2591530204a76fecc843529ade56afe865dd2657 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 6 Jan 2010 15:48:42 -0800 Subject: usb: serial: fix memory leak in generic driver Fix a regression introduced by commit 715b1dc01fe44537e8fce9566e4bb48d6821d84b ("USB: usb_debug, usb_generic_serial: implement multi urb write"). URB transfer buffer was never freed when using multi-urb writes. Currently the only driver enabling multi-urb writes is usb_debug. Signed-off-by: Johan Hovold Cc: Greg KH Acked-by: Jason Wessel Cc: stable Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 5ce033ab9b9..83443d6306d 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -489,6 +489,8 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) dbg("%s - port %d", __func__, port->number); if (port->serial->type->max_in_flight_urbs) { + kfree(urb->transfer_buffer); + spin_lock_irqsave(&port->lock, flags); --port->urbs_in_flight; port->tx_bytes_flight -= urb->transfer_buffer_length; -- cgit v1.2.3 From a91b593edd4b3e8aa91f671b763b27b8119eb49d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 22 Dec 2009 23:16:32 -0500 Subject: USB: fix bitmask merge error This patch adds a mask bit which was mistakenly omitted from the as1311 patch (usb-storage: add BAD_SENSE flag). Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 5a53d4f0dd1..e9f995486ec 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -434,7 +434,8 @@ static void adjust_quirks(struct us_data *us) u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor); u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct); unsigned f = 0; - unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY | + unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE | + US_FL_FIX_CAPACITY | US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE | US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | -- cgit v1.2.3 From acbe2febe71abb2360b008e9ab3ee5c44169f78c Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 12 Jan 2010 12:32:50 +0100 Subject: USB: Don't use GFP_KERNEL while we cannot reset a storage device Memory allocations with GFP_KERNEL can cause IO to a storage device which can fail resulting in a need to reset the device. Therefore GFP_KERNEL cannot be safely used between usb_lock_device() and usb_unlock_device(). Replace by GFP_NOIO. Signed-off-by: Oliver Neukum Cc: stable Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/message.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 96f11715cd2..355dffcc23b 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -494,7 +494,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, return 0; /* allocate 2^1 pages = 8K (on i386); * should be more than enough for one device */ - pages_start = (char *)__get_free_pages(GFP_KERNEL, 1); + pages_start = (char *)__get_free_pages(GFP_NOIO, 1); if (!pages_start) return -ENOMEM; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 1b994846e8e..9bc95fec793 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -906,11 +906,11 @@ char *usb_cache_string(struct usb_device *udev, int index) if (index <= 0) return NULL; - buf = kmalloc(MAX_USB_STRING_SIZE, GFP_KERNEL); + buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO); if (buf) { len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE); if (len > 0) { - smallbuf = kmalloc(++len, GFP_KERNEL); + smallbuf = kmalloc(++len, GFP_NOIO); if (!smallbuf) return buf; memcpy(smallbuf, buf, len); @@ -1731,7 +1731,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (cp) { nintf = cp->desc.bNumInterfaces; new_interfaces = kmalloc(nintf * sizeof(*new_interfaces), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces) { dev_err(&dev->dev, "Out of memory\n"); return -ENOMEM; @@ -1740,7 +1740,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration) for (; n < nintf; ++n) { new_interfaces[n] = kzalloc( sizeof(struct usb_interface), - GFP_KERNEL); + GFP_NOIO); if (!new_interfaces[n]) { dev_err(&dev->dev, "Out of memory\n"); ret = -ENOMEM; -- cgit v1.2.3 From 1b9a38bfa6e664ff02511314f5586d711c83cc91 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:17:55 -0500 Subject: USB: EHCI: fix handling of unusual interrupt intervals This patch (as1320) fixes two problems related to interrupt-URB scheduling in ehci-hcd. URBs with an interval of 2 or 4 microframes aren't handled. For the time being, the patch reduces to interval to 1 uframe. URBs are constrained to have an interval no larger than 1024 frames by usb_submit_urb(). But some EHCI controllers allow use of a schedule as short as 256 frames; for these controllers we may have to decrease the interval to the actual schedule length. The second problem isn't very significant since few devices expose interrupt endpoints with an interval larger than 256 frames. But the first problem is critical; it will prevent the kernel from working with devices having interrupt intervals of 2 or 4 uframes. Signed-off-by: Alan Stern Cc: stable Tested-by: Glynn Farrow Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a427d3b0063..89521775c56 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -849,9 +849,10 @@ qh_make ( * But interval 1 scheduling is simpler, and * includes high bandwidth. */ - dbg ("intr period %d uframes, NYET!", - urb->interval); - goto done; + urb->interval = 1; + } else if (qh->period > ehci->periodic_size) { + qh->period = ehci->periodic_size; + urb->interval = qh->period << 3; } } else { int think_time; @@ -874,6 +875,10 @@ qh_make ( usb_calc_bus_time (urb->dev->speed, is_input, 0, max_packet (maxp))); qh->period = urb->interval; + if (qh->period > ehci->periodic_size) { + qh->period = ehci->periodic_size; + urb->interval = qh->period; + } } } -- cgit v1.2.3 From cec3a53c7fe794237b582e8e77fc0e48465e65ee Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:18:20 -0500 Subject: USB: EHCI & UHCI: fix race between root-hub suspend and port resume This patch (as1321) fixes a problem with EHCI and UHCI root-hub suspends: If the suspend occurs while a port is trying to resume, the resume doesn't finish and simply gets lost. When remote wakeup is enabled, this is undesirable behavior. The patch checks first to see if any port resumes are in progress, and if they are then it fails the root-hub suspend with -EBUSY. Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 20 +++++++++++++++++++- drivers/usb/host/uhci-hcd.c | 15 ++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 2c6571c05f3..c75d9270c75 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -120,9 +120,26 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) del_timer_sync(&ehci->watchdog); del_timer_sync(&ehci->iaa_watchdog); - port = HCS_N_PORTS (ehci->hcs_params); spin_lock_irq (&ehci->lock); + /* Once the controller is stopped, port resumes that are already + * in progress won't complete. Hence if remote wakeup is enabled + * for the root hub and any ports are in the middle of a resume or + * remote wakeup, we must fail the suspend. + */ + if (hcd->self.root_hub->do_remote_wakeup) { + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + if (ehci->reset_done[port] != 0) { + spin_unlock_irq(&ehci->lock); + ehci_dbg(ehci, "suspend failed because " + "port %d is resuming\n", + port + 1); + return -EBUSY; + } + } + } + /* stop schedules, clean any completed work */ if (HC_IS_RUNNING(hcd->state)) { ehci_quiesce (ehci); @@ -138,6 +155,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) */ ehci->bus_suspended = 0; ehci->owned_ports = 0; + port = HCS_N_PORTS(ehci->hcs_params); while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 5cd0e48f67f..99cd00fd351 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -749,7 +749,20 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) spin_lock_irq(&uhci->lock); if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) rc = -ESHUTDOWN; - else if (!uhci->dead) + else if (uhci->dead) + ; /* Dead controllers tell no tales */ + + /* Once the controller is stopped, port resumes that are already + * in progress won't complete. Hence if remote wakeup is enabled + * for the root hub and any ports are in the middle of a resume or + * remote wakeup, we must fail the suspend. + */ + else if (hcd->self.root_hub->do_remote_wakeup && + uhci->resuming_ports) { + dev_dbg(uhci_dev(uhci), "suspend failed because a port " + "is resuming\n"); + rc = -EBUSY; + } else suspend_rh(uhci, UHCI_RH_SUSPENDED); spin_unlock_irq(&uhci->lock); return rc; -- cgit v1.2.3 From 49d0f078f494b9d81e820a13dd8093a9bfb0b6b1 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 8 Jan 2010 11:18:38 -0500 Subject: USB: add missing delay during remote wakeup This patch (as1330) fixes a bug in khbud's handling of remote wakeups. When a device sends a remote-wakeup request, the parent hub (or the host controller driver, for directly attached devices) begins the resume sequence and notifies khubd when the sequence finishes. At this point the port's SUSPEND feature is automatically turned off. However the device needs an additional 10-ms resume-recovery time (TRSMRCY in the USB spec). Khubd does not wait for this delay if the SUSPEND feature is off, and as a result some devices fail to behave properly following a remote wakeup. This patch adds the missing delay to the remote-wakeup path. It also extends the resume-signalling delay used by ehci-hcd and uhci-hcd from 20 ms (the value in the spec) to 25 ms (the value we use for non-remote-wakeup resumes). The extra time appears to help some devices. Signed-off-by: Alan Stern Cc: stable Cc: Rickard Bellini Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 3 +++ drivers/usb/host/ehci-hcd.c | 5 +++-- drivers/usb/host/uhci-hub.c | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0cec6caf6e9..b9f5fcd713e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3347,6 +3347,9 @@ static void hub_events(void) USB_PORT_FEAT_C_SUSPEND); udev = hdev->children[i-1]; if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + usb_lock_device(udev); ret = remote_wakeup(hdev-> children[i-1]); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5859522d6ed..1ec3857f22e 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -787,9 +787,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* start 20 msec resume signaling from this port, * and make khubd collect PORT_STAT_C_SUSPEND to - * stop that signaling. + * stop that signaling. Use 5 ms extra for safety, + * like usb_port_resume() does. */ - ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); + ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); mod_timer(&hcd->rh_timer, ehci->reset_done[i]); } diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 885b585360b..8270055848c 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -167,7 +167,7 @@ static void uhci_check_ports(struct uhci_hcd *uhci) /* Port received a wakeup request */ set_bit(port, &uhci->resuming_ports); uhci->ports_timeout = jiffies + - msecs_to_jiffies(20); + msecs_to_jiffies(25); /* Make sure we see the port again * after the resuming period is over. */ -- cgit v1.2.3 From b132b04e193908a94d95065d0628f8fb0159cc55 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Jan 2010 10:33:19 -0800 Subject: USB: add speed values for USB 3.0 and wireless controllers These controllers say "unknown" for their speed in sysfs, which obviously isn't correct. Reported-by: Kurt Garloff Cc: Sarah Sharp Cc: David Vrabel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 485edf937f2..5f3908f6e2d 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -115,6 +115,12 @@ show_speed(struct device *dev, struct device_attribute *attr, char *buf) case USB_SPEED_HIGH: speed = "480"; break; + case USB_SPEED_VARIABLE: + speed = "480"; + break; + case USB_SPEED_SUPER: + speed = "5000"; + break; default: speed = "unknown"; } -- cgit v1.2.3 From 04a723ea9c53ba608b0411aa36948bb57c51a08e Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 6 Jan 2010 10:16:51 -0800 Subject: USB: Fix duplicate sysfs problem after device reset. Borislav Petkov reports issues with duplicate sysfs endpoint files after a resume from a hibernate. It turns out that the code to support alternate settings under xHCI has issues when a device with a non-default alternate setting is reset during the hibernate: [ 427.681810] Restarting tasks ... [ 427.681995] hub 1-0:1.0: state 7 ports 6 chg 0004 evt 0000 [ 427.682019] usb usb3: usb resume [ 427.682030] ohci_hcd 0000:00:12.0: wakeup root hub [ 427.682191] hub 1-0:1.0: port 2, status 0501, change 0000, 480 Mb/s [ 427.682205] usb 1-2: usb wakeup-resume [ 427.682226] usb 1-2: finish reset-resume [ 427.682886] done. [ 427.734658] ehci_hcd 0000:00:12.2: port 2 high speed [ 427.734663] ehci_hcd 0000:00:12.2: GetStatus port 2 status 001005 POWER sig=se0 PE CONNECT [ 427.746682] hub 3-0:1.0: hub_reset_resume [ 427.746693] hub 3-0:1.0: trying to enable port power on non-switchable hub [ 427.786715] usb 1-2: reset high speed USB device using ehci_hcd and address 2 [ 427.839653] ehci_hcd 0000:00:12.2: port 2 high speed [ 427.839666] ehci_hcd 0000:00:12.2: GetStatus port 2 status 001005 POWER sig=se0 PE CONNECT [ 427.847717] ohci_hcd 0000:00:12.0: GetStatus roothub.portstatus [1] = 0x00010100 CSC PPS [ 427.915497] hub 1-2:1.0: remove_intf_ep_devs: if: ffff88022f9e8800 ->ep_devs_created: 1 [ 427.915774] hub 1-2:1.0: remove_intf_ep_devs: bNumEndpoints: 1 [ 427.915934] hub 1-2:1.0: if: ffff88022f9e8800: endpoint devs removed. [ 427.916158] hub 1-2:1.0: create_intf_ep_devs: if: ffff88022f9e8800 ->ep_devs_created: 0, ->unregistering: 0 [ 427.916434] hub 1-2:1.0: create_intf_ep_devs: bNumEndpoints: 1 [ 427.916609] ep_81: create, parent hub [ 427.916632] ------------[ cut here ]------------ [ 427.916644] WARNING: at fs/sysfs/dir.c:477 sysfs_add_one+0x82/0x96() [ 427.916649] Hardware name: System Product Name [ 427.916653] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:12.2/usb1/1-2/1-2:1.0/ep_81' [ 427.916658] Modules linked in: binfmt_misc kvm_amd kvm powernow_k8 cpufreq_ondemand cpufreq_powersave cpufreq_userspace freq_table cpufreq_conservative ipv6 vfat fat +8250_pnp 8250 pcspkr ohci_hcd serial_core k10temp edac_core [ 427.916694] Pid: 278, comm: khubd Not tainted 2.6.33-rc2-00187-g08d869a-dirty #13 [ 427.916699] Call Trace: The problem is caused by a mismatch between the USB core's view of the device state and the USB device and xHCI host's view of the device state. After the device reset and re-configuration, the device and the xHCI host think they are using alternate setting 0 of all interfaces. However, the USB core keeps track of the old state, which may include non-zero alternate settings. It uses intf->cur_altsetting to keep the endpoint sysfs files for the old state across the reset. The bandwidth allocation functions need to know what the xHCI host thinks the current alternate settings are, so original patch set intf->cur_altsetting to the alternate setting 0. This caused duplicate endpoint files to be created. The solution is to not set intf->cur_altsetting before calling usb_set_interface() in usb_reset_and_verify_device(). Instead, we add a new flag to struct usb_interface to tell usb_hcd_alloc_bandwidth() to use alternate setting 0 as the currently installed alternate setting. Signed-off-by: Sarah Sharp Tested-by: Borislav Petkov Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 18 ++++++++++++++++++ drivers/usb/core/hub.c | 15 +++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0495fa65122..80995ef0868 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1684,6 +1684,24 @@ int usb_hcd_alloc_bandwidth(struct usb_device *udev, } } if (cur_alt && new_alt) { + struct usb_interface *iface = usb_ifnum_to_if(udev, + cur_alt->desc.bInterfaceNumber); + + if (iface->resetting_device) { + /* + * The USB core just reset the device, so the xHCI host + * and the device will think alt setting 0 is installed. + * However, the USB core will pass in the alternate + * setting installed before the reset as cur_alt. Dig + * out the alternate setting 0 structure, or the first + * alternate setting if a broken device doesn't have alt + * setting 0. + */ + cur_alt = usb_altnum_to_altsetting(iface, 0); + if (!cur_alt) + cur_alt = &iface->altsetting[0]; + } + /* Drop all the endpoints in the current alt setting */ for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) { ret = hcd->driver->drop_endpoint(hcd, udev, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b9f5fcd713e..35cc8b9ba1f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3695,19 +3695,14 @@ static int usb_reset_and_verify_device(struct usb_device *udev) usb_enable_interface(udev, intf, true); ret = 0; } else { - /* We've just reset the device, so it will think alt - * setting 0 is installed. For usb_set_interface() to - * work properly, we need to set the current alternate - * interface setting to 0 (or the first alt setting, if - * the device doesn't have alt setting 0). + /* Let the bandwidth allocation function know that this + * device has been reset, and it will have to use + * alternate setting 0 as the current alternate setting. */ - intf->cur_altsetting = - usb_find_alt_setting(config, i, 0); - if (!intf->cur_altsetting) - intf->cur_altsetting = - &config->intf_cache[i]->altsetting[0]; + intf->resetting_device = 1; ret = usb_set_interface(udev, desc->bInterfaceNumber, desc->bAlternateSetting); + intf->resetting_device = 0; } if (ret < 0) { dev_err(&udev->dev, "failed to restore interface %d " -- cgit v1.2.3 From ae35fe9e8abe828b25053cd3efdc6953fbb710e3 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Thu, 7 Jan 2010 04:17:32 +0300 Subject: USB: FHCI: avoid NULL pointer dereference Assign fhci only if usb is not NULL. Signed-off-by: Alexander Beregalov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fhci-hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 0951818ef93..78e7c3cfcb7 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -242,9 +242,10 @@ err: static void fhci_usb_free(void *lld) { struct fhci_usb *usb = lld; - struct fhci_hcd *fhci = usb->fhci; + struct fhci_hcd *fhci; if (usb) { + fhci = usb->fhci; fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF); fhci_ep0_free(usb); kfree(usb->actual_frame); -- cgit v1.2.3 From c0d74142531c7ec23bb29885aec8f924ee4c1a46 Mon Sep 17 00:00:00 2001 From: Colin Tuckley Date: Thu, 7 Jan 2010 11:22:47 +0000 Subject: USB: Fix level of isp1760 Reloading ptd error message This error message is not actually an error, it's an information message. It is triggered when a transfer which ended in a NAQ is retried successfully by the hardware. Signed-off-by: Colin Tuckley Cc: Sebastian Andrzej Siewior Cc: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 9600a58299d..27b8f7cb447 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -1039,12 +1039,12 @@ static void do_atl_int(struct usb_hcd *usb_hcd) if (!nakcount && (dw3 & DW3_QTD_ACTIVE)) { u32 buffstatus; - /* XXX + /* * NAKs are handled in HW by the chip. Usually if the * device is not able to send data fast enough. - * This did not trigger for a long time now. + * This happens mostly on slower hardware. */ - printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: " + printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: " "%d of %zu done: %08x cur: %08x\n", qtd, urb, qh, PTD_XFERRED_LENGTH(dw3), qtd->length, done_map, -- cgit v1.2.3 From 10d2cdb6102669279bee2d9a00a22431b74583d5 Mon Sep 17 00:00:00 2001 From: Ryan May Date: Wed, 6 Jan 2010 10:09:25 -0600 Subject: USB: fix usbstorage for 2770:915d delivers no FAT Resolves kernel.org bug 14914. Remove entry for 2770:915d (usb digital camera with mass storage support) from unusual_devs.h. The fix triggered by the entry causes the file system on the camera to be completely inaccessible (no partition table, the device is not mountable). The patch works, but let me clarify a few things about it. All the patch does is remove the entry for this device from the drivers/usb/storage/unusual_devs.h, which is supposed to help with a problem with the device's reported size (I think). I'm pretty sure it was originally added for a reason, so I'm not sure removing it won't cause other problems to reappear. Also, I should note that this unusual_devs.h entry was present (and activating workarounds) in 2.6.29, but in that version everything works fine. Starting with 2.6.30, things no longer work. Signed-off-by: Ryan May Cc: Rohan Hart Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 64a0a2c27e1..c932f905318 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1807,13 +1807,6 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_GO_SLOW ), -/* Reported by Rohan Hart */ -UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010, - "INTOVA", - "Pixtreme", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - /* Reported by Frederic Marchal * Mio Moov 330 */ -- cgit v1.2.3 From 96b85179b464cc80d85b5c602af119d1dd6d50bb Mon Sep 17 00:00:00 2001 From: Lothar Wassmann Date: Fri, 15 Jan 2010 08:04:55 -0500 Subject: USB: isp1362: better 64bit printf warning fixes Some hosts that treat the return value of sizeof differently from unsigned long might still hit warnings. So use %zu for sizeof() values. This is a better version of the previous commit b0a9cf297e58721933. Signed-off-by: Lothar Wassmann Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 73352f3739b..8d3104441f1 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2270,10 +2270,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd) dev_info(hcd->self.controller, "ISP1362 Memory usage:\n"); dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n", istl_size / 2, istl_size, 0, istl_size / 2); - dev_info(hcd->self.controller, " INTL: %4d * (%3lu+8): %4d @ $%04x\n", + dev_info(hcd->self.controller, " INTL: %4d * (%3zu+8): %4d @ $%04x\n", ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE, intl_size, istl_size); - dev_info(hcd->self.controller, " ATL : %4d * (%3lu+8): %4d @ $%04x\n", + dev_info(hcd->self.controller, " ATL : %4d * (%3zu+8): %4d @ $%04x\n", atl_buffers, atl_blksize - PTD_HEADER_SIZE, atl_size, istl_size + intl_size); dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total, -- cgit v1.2.3 From 0a2fea2e0dea9df8ead1cb45e4b9cd68e1b1d29b Mon Sep 17 00:00:00 2001 From: Lothar Wassmann Date: Fri, 15 Jan 2010 14:42:02 -0500 Subject: USB: isp1362: fix build failure on ARM systems via irq_flags cleanup There was some left over #ifdef ARM logic that is outdated but no one really noticed. So instead of relying on this tricky logic, properly load and utilize the platform irq_flags resources. Reported-by: Ben Hutchings Signed-off-by: Lothar Wassmann Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 8d3104441f1..42971657fde 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2697,6 +2697,8 @@ static int __init isp1362_probe(struct platform_device *pdev) void __iomem *data_reg; int irq; int retval = 0; + struct resource *irq_res; + unsigned int irq_flags = 0; /* basic sanity checks first. board-specific init logic should * have initialized this the three resources and probably board @@ -2710,11 +2712,12 @@ static int __init isp1362_probe(struct platform_device *pdev) data = platform_get_resource(pdev, IORESOURCE_MEM, 0); addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq = platform_get_irq(pdev, 0); - if (!addr || !data || irq < 0) { + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!addr || !data || !irq_res) { retval = -ENODEV; goto err1; } + irq = irq_res->start; #ifdef CONFIG_USB_HCD_DMA if (pdev->dev.dma_mask) { @@ -2781,12 +2784,16 @@ static int __init isp1362_probe(struct platform_device *pdev) } #endif -#ifdef CONFIG_ARM - if (isp1362_hcd->board) - set_irq_type(irq, isp1362_hcd->board->int_act_high ? IRQT_RISING : IRQT_FALLING); -#endif + if (irq_res->flags & IORESOURCE_IRQ_HIGHEDGE) + irq_flags |= IRQF_TRIGGER_RISING; + if (irq_res->flags & IORESOURCE_IRQ_LOWEDGE) + irq_flags |= IRQF_TRIGGER_FALLING; + if (irq_res->flags & IORESOURCE_IRQ_HIGHLEVEL) + irq_flags |= IRQF_TRIGGER_HIGH; + if (irq_res->flags & IORESOURCE_IRQ_LOWLEVEL) + irq_flags |= IRQF_TRIGGER_LOW; - retval = usb_add_hcd(hcd, irq, IRQF_TRIGGER_LOW | IRQF_DISABLED | IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, irq_flags | IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err6; pr_info("%s, irq %d\n", hcd->product_desc, irq); -- cgit v1.2.3 From c1fa347f20f17f14a4a1575727fa24340e8a9117 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 19 Jan 2010 14:21:45 +0000 Subject: e1000/e1000e/igb/igbvf/ixgb/ixgbe: Fix tests of unsigned in *_tx_map() The variable count and i are unsigned so the (<|>=)0 tests do not work. Signed-off-by: Roel Kluin Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 10 +++++----- drivers/net/e1000e/netdev.c | 10 +++++----- drivers/net/igbvf/netdev.c | 10 +++++----- drivers/net/ixgb/ixgb_main.c | 10 +++++----- drivers/net/ixgbe/ixgbe_main.c | 10 +++++----- 5 files changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7e855f9bbd9..b3f67b41627 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2802,13 +2802,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; e1000_unmap_and_free_tx_resource(adapter, buffer_info); } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c45965a256b..f91f247ed6a 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3962,13 +3962,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; e1000_put_txbuf(adapter, buffer_info);; } diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 0dbd0320023..10e038adba0 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -2163,14 +2163,14 @@ dma_error: buffer_info->length = 0; buffer_info->next_to_watch = 0; buffer_info->mapped_as_page = false; - count--; + if (count) + count--; /* clear timestamp and dma mappings for remaining portion of packet */ - while (count >= 0) { - count--; - i--; - if (i < 0) + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; igbvf_put_txbuf(adapter, buffer_info); } diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index bcd0f01d5fe..593d1a4f217 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1363,13 +1363,13 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb, dma_error: dev_err(&pdev->dev, "TX DMA map failed\n"); buffer_info->dma = 0; - count--; - - while (count >= 0) { + if (count) count--; - i--; - if (i < 0) + + while (count--) { + if (i==0) i += tx_ring->count; + i--; buffer_info = &tx_ring->buffer_info[i]; ixgb_unmap_and_free_tx_resource(adapter, buffer_info); } diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 9c9202f40b1..6d61add27a0 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -5167,14 +5167,14 @@ dma_error: tx_buffer_info->dma = 0; tx_buffer_info->time_stamp = 0; tx_buffer_info->next_to_watch = 0; - count--; + if (count) + count--; /* clear timestamp and dma mappings for remaining portion of packet */ - while (count >= 0) { - count--; - i--; - if (i < 0) + while (count--) { + if (i==0) i += tx_ring->count; + i--; tx_buffer_info = &tx_ring->tx_buffer_info[i]; ixgbe_unmap_and_free_tx_resource(adapter, tx_buffer_info); } -- cgit v1.2.3 From 40a14deaf411592b57cb0720f0e8004293ab9865 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:38 +0000 Subject: e1000: enhance frame fragment detection Originally From: Neil Horman Modified by: Jesse Brandeburg Hey all- A security discussion was recently given: http://events.ccc.de/congress/2009/Fahrplan//events/3596.en.html And a patch that I submitted awhile back was brought up. Apparently some of their testing revealed that they were able to force a buffer fragment in e1000 in which the trailing fragment was greater than 4 bytes. As a result the fragment check I introduced failed to detect the fragement and a partial invalid frame was passed up into the network stack. I've written this patch to correct it. I'm in the process of testing it now, but it makes good logical sense to me. Effectively it maintains a per-adapter state variable which detects a non-EOP frame, and discards it and subsequent non-EOP frames leading up to _and_ _including_ the next positive-EOP frame (as it is by definition the last fragment). This should prevent any and all partial frames from entering the network stack from e1000. Signed-off-by: Jesse Brandeburg Acked-by: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000.h | 2 ++ drivers/net/e1000/e1000_main.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 2a567df3ea7..e8932db7ee7 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -326,6 +326,8 @@ struct e1000_adapter { /* for ioport free */ int bars; int need_ioport; + + bool discarding; }; enum e1000_state_t { diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b3f67b41627..a53a2017c53 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3850,13 +3850,22 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) { + * packet, if thats the case we need to toss it. In fact, we + * to toss every packet with the EOP bit clear and the next + * frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->discarding = true; + + if (adapter->discarding) { /* All receives must fit into a single buffer */ E1000_DBG("%s: Receive packet consumed multiple" " buffers\n", netdev->name); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->discarding = false; goto next_desc; } -- cgit v1.2.3 From b94b50289622e816adc9f94111cfc2679c80177c Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 19 Jan 2010 14:15:59 +0000 Subject: e1000e: enhance frame fragment detection Originally patched by Neil Horman e1000e could with a jumbo frame enabled interface, and packet split disabled, receive a packet that would overflow a single rx buffer. While in practice very hard to craft a packet that could abuse this, it is possible. this is related to CVE-2009-4538 Signed-off-by: Jesse Brandeburg CC: Neil Horman Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 1 + drivers/net/e1000e/netdev.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index d6ee28f6ea0..d236efaf747 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -421,6 +421,7 @@ struct e1000_info { /* CRC Stripping defines */ #define FLAG2_CRC_STRIPPING (1 << 0) #define FLAG2_HAS_PHY_WAKEUP (1 << 1) +#define FLAG2_IS_DISCARDING (1 << 2) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index f91f247ed6a..1ea395b6c99 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -450,13 +450,23 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); - /* !EOP means multiple descriptors were used to store a single - * packet, also make sure the frame isn't just CRC only */ - if (!(status & E1000_RXD_STAT_EOP) || (length <= 4)) { + /* + * !EOP means multiple descriptors were used to store a single + * packet, if that's the case we need to toss it. In fact, we + * need to toss every packet with the EOP bit clear and the + * next frame that _does_ have the EOP bit set, as it is by + * definition only a frame fragment + */ + if (unlikely(!(status & E1000_RXD_STAT_EOP))) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { /* All receives must fit into a single buffer */ e_dbg("Receive packet consumed multiple buffers\n"); /* recycle */ buffer_info->skb = skb; + if (status & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -745,10 +755,16 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, PCI_DMA_FROMDEVICE); buffer_info->dma = 0; - if (!(staterr & E1000_RXD_STAT_EOP)) { + /* see !EOP comment in other rx routine */ + if (!(staterr & E1000_RXD_STAT_EOP)) + adapter->flags2 |= FLAG2_IS_DISCARDING; + + if (adapter->flags2 & FLAG2_IS_DISCARDING) { e_dbg("Packet Split buffers didn't pick up the full " "packet\n"); dev_kfree_skb_irq(skb); + if (staterr & E1000_RXD_STAT_EOP) + adapter->flags2 &= ~FLAG2_IS_DISCARDING; goto next_desc; } @@ -1118,6 +1134,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; + adapter->flags2 &= ~FLAG2_IS_DISCARDING; writel(0, adapter->hw.hw_addr + rx_ring->head); writel(0, adapter->hw.hw_addr + rx_ring->tail); -- cgit v1.2.3 From 26d92f9276a56d55511a427fb70bd70886af647a Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 21 Jan 2010 22:52:08 -0800 Subject: be2net: fix bug in rx page posting Pages are posted to the rxq in such a way that more than one frag can share the page. The last frag that uses the page unmaps the page. In the case when a page is not fully used (due to lack of space in rxq) the last frag that uses the page is not being set as a "last_page_user"; instead, the next frag in the rxq is incorrectly being set. The fix has also been tested on ppc64 with 64k pages... Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3a1f7902c16..33ab8c7f14f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -910,7 +910,7 @@ static inline struct page *be_alloc_pages(u32 size) static void be_post_rx_frags(struct be_adapter *adapter) { struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; - struct be_rx_page_info *page_info = NULL; + struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; struct be_queue_info *rxq = &adapter->rx_obj.q; struct page *pagep = NULL; struct be_eth_rx_d *rxd; @@ -941,7 +941,6 @@ static void be_post_rx_frags(struct be_adapter *adapter) rxd = queue_head_node(rxq); rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); - queue_head_inc(rxq); /* Any space left in the current big page for another frag? */ if ((page_offset + rx_frag_size + rx_frag_size) > @@ -949,10 +948,13 @@ static void be_post_rx_frags(struct be_adapter *adapter) pagep = NULL; page_info->last_page_user = true; } + + prev_page_info = page_info; + queue_head_inc(rxq); page_info = &page_info_tbl[rxq->head]; } if (pagep) - page_info->last_page_user = true; + prev_page_info->last_page_user = true; if (posted) { atomic_add(posted, &rxq->used); -- cgit v1.2.3